안녕하세요.
php를 이용하여 예전에 만들어본 검색엔진 코드입니다.
모델은 벡터모델을 이용하여 제작하였습니다.
랭킹은 바이그램 색인을 이용하여 역색인 파일을 만들고
가중치를 tf*idf로 계산하였습니다.
단점으로는 단어간의 독립성으로 인해 발생하는 문제를 해결하진 못했습니다.. ㅠㅠ
알고리즘입니다.
1. 검색을 하기 전 문서 DB를 만든다(Make_DB()). 문서 DB는 크롤러를 통해 수집할 수도 있지만 없기에 직접 DB에 입력하기로 했다.
2. 만들어진 문서 DB를 토대로 바이그램을 하여 역색인 단어 DB를 만든다 (Rever_DB())
3. 2의 단계까지 검색 전 데이터 셋을 만드는 과정이다. 이후 index페이지에서 검색을 한다.(Input())
4. 검색 시 Rever_DB에서 단어를 찾고 그 결과를 저장한다.
4. 저장한 값을 가중치를 통해 순서를 정한다 (Rank())
5. 순서가 결정된 검색 순서대로 출력을 한다. (Output())
6. 만약 검색 시 DB에 단어가 없다면 검색된 단어가 없다고 출력을 한다. (NoData)
이러한 알고리즘을 기반으로 다음과 같이 코딩했습니다.
---------------------------------------------Index.php----------------------------------------------
<!-- 다음은 첫 화면 페이지를 나타냅니다. -->
<html>
<head>
<title>검색</title> <!-- 제목 -->
<meta charset="utf-8">
</head>
<body>
<form method="post" action="search.php" align="center"> <!-- 폼 크기 설정 -->
<div id="logo" style="color:rgb(121, 165, 228); width:100% text-align:center">
<h1>검색 사이트 입니다.</h1>
</div>
<input type="text" name="search" style="border:10px solid rgb(121, 165, 228); background-color:rgb(219, 232, 251); padding:10px;"/>
<input type="submit" value="검색" style="width:100px; height:55px;"/>
</form>
</body>
</html>
--------------------------------------------Rever.php----------------------------------------------
<!-- 다음은 문서 DB의 본문내용을 역색인 파일로 만듦니다. -->
<?php
header("Content-type: text/html; charset=utf-8");
$conn = mysql_connect("localhost", "root", "apmsetup") or die(mysql_error()); // DB접속
mysql_select_db("G"); // DB 선택
mysql_query("SET NAMES 'utf8'"); // DB charset과 맞춤
$tablename = "doc"; // Table 선택
$sql = "select * from $tablename"; // table의 모든 데이터를 가져옴
$result = mysql_query($sql) or die (mysql_error()); // 쿼리문 시작
$tablename1 = "rever";
$sql1 = "select * from $tablename1"; // table의 모든 데이터를 가져옴
$result1 = mysql_query($sql1) or die (mysql_error()); // 쿼리문 시작
function mb_str_split($str){
$ret = array();
for ($i=0; $i<mb_strlen($str, "utf-8"); $i++){
array_push($ret, mb_substr($str, $i, 2, "utf-8"));
}
return $ret;
}
//$row = mysql_fetch_array($result)
//$row1 = $row
while($row = mysql_fetch_array($result))
{
$dnoun_tmp = preg_replace("[\(|\)|\ㆍ|\ |\[|\]|\{|\}|\,|\.|\·|\?|\!|\'|\\|\"]", "", $row[content]);
$arr = mb_str_split($dnoun_tmp);
$a = count($arr);
//echo $arr[1];
for($i = 0; $i <$a; $i++)
{
$sql = "INSERT INTO `g`.`rever` (
`num` ,
`text` ,
`doc_num`
)
VALUES (
NULL , '$arr[$i]', '$row[doc_num]'
);";
$result1 = mysql_query($sql) or die (mysql_error());
}
}
?>
--------------------------------------------Search.php---------------------------------------------
<!-- 다음은 index.php에서 Post로 전달받은 값을 질의어로하여 검색을 합니다. -->
<?php
header("Content-type: text/html; charset=utf-8"); // DB와 charset을 맟춤
$conn = mysql_connect("localhost", "root", "apmsetup") or die(mysql_error()); // DB접속
mysql_select_db("G"); // DB 선택
mysql_query("SET NAMES 'utf8'"); // DB charset과 맞춤
$tablename = "doc"; // 문서 Table 선택
$sql = "select * from $tablename"; // table의 모든 데이터를 가져옴
$result = mysql_query($sql) or die (mysql_error()); // 쿼리문 시작
$tablename1 = "rever"; // 역색인 파일 Table 선택
$sql1 = "select * from $tablename1"; // table의 모든 데이터를 가져옴
$result1 = mysql_query($sql1) or die (mysql_error()); // 쿼리문 시작
function mb_str_split($str){ // 이 함수는 한글을 2글자씩 잘라서 배열에 넣음
$ret = array();
for ($i=0; $i<mb_strlen($str, "utf-8"); $i++){
array_push($ret, mb_substr($str, $i, 2, "utf-8"));
}
return $ret;
}
?>
<html>
<head>
<title>Search</title>
<meta charset="utf-8">
</head>
<body>
<form method="post" action="search.php" align="center"> <!--검색 시 search에게 post로 보냄-->
<div id="logo" style="color:rgb(121, 165, 228); width:100% text-align:center">
<h1>검색 사이트 입니다.</h1>
</div>
<input type="text" name="search" style="border:10px solid rgb(121, 165, 228); background-color:rgb(219, 232, 251); padding:10px;"/>
<input type="submit" value="검색" style="width:100px; height:55px;"/>
</form>
</br>
<?php
echo "<table align = 'center' width='1000px'>";
echo "<tr><th>$_POST[search]"; // post로 넘어온 값을 띄워줌
echo"의 검색결과";
echo "입니다.</th></tr>";
$ct; // TF 저장 공간
$q; // 질의문
$doc_num; // 문서 번호 저장 공간
$content; // 문서 내용 저장 공간
$title; // 문서 재목 저장공간
$url; // 문서 url 저장 공간
$w = 0; // 처음 시작 지점 설정 변수
$ftitle; // 최종 출력할 제목
$furl; // 최종 출력할 url
$fcontent; // 최종 출력할 문서 내용
$fdoc_num; // 최종으로 저장할 문서의 번호
$input = $_POST[search]; // 질의어를 저장하는 변수
$dnoun_tmp = preg_replace("[\(|\)|\ㆍ|\ |\[|\]|\{|\}|\,|\.|\·|\?|\!|\'|\\|\"]", "", $input); // 질의어의 빈칸을 없앰
$query = mb_str_split($dnoun_tmp); //질의어를 2글자로 자름
$qq = count($query);
while($dd = mysql_fetch_array($result1)) // 역색인 파일을 검색함
{
if ($dd[text]==$query[0]) // 질의어와 역색인 파일이 같다면
{
if($w==1)
{
for($i=0; $i < $c; $i++) // 검색된 내용 비교하여 저장
{
if($doc_num[$i] == $dd[doc_num]) // TF증가
{
$ct[$i] ++;
break;
}
if($doc_num[$i] != $dd[doc_num]) // for문 제어
{
$hh++;
}
if($hh == $c) // 새로운 색인어가 들어온다면 새로 단어 저장
{
$q[$c] = $input;
$doc_num[$c] = $dd[doc_num];
$ct[$c] ++;
while($row = mysql_fetch_array($result)) // 역색인DB를 이용하여 postDB생성
{
if($doc_num[$c]==$row[doc_num])
{
$title[$c] = $row[title];
$content[$c] = $row[content];
$url[$c] = $row[url];
break;
}
}
}
}
}
$hh = 0;
if($w==0) // 초기 시작
{
$q[0] = $input;
$doc_num[0] = $dd[doc_num];
$ct[0] ++;
$w++;
while($row = mysql_fetch_array($result)) //index파일의 문서번호를 이용하여 본문 문서 내용 저장
{
if($doc_num[0]==$row[doc_num])
{
$title[0] = $row[title];
$content[0] = $row[content];
$url[0] = $row[url];
break;
}
}
}
$c = count($doc_num); //배열의 길이
}
}
if($c == 0) // 검색결과 없을 시
{
echo "<tr><th>검색된 결과가 없습니다.</th></tr>";
}
if ($c!=0) // 검색결과 있을 시
{
$fct=$ct;
rsort($fct);
$m = log(100/$c, 2);
for($j=0; $j<$c; $j++) //검색된 문서들을 백터 모델로 랭킹함
{
for ($l = 0; $l < count($fct); $l++)
{
if($fct[$j]==$ct[$l])
{
if($fdoc_num[$j] == NULL)
{
$cal[$j] = $ct[$l];
$ct[$l]=NULL;
$fdoc_num[$j] = $doc_num[$l];
$ftitle[$j] = $title[$l];
$furl[$j] = $url[$l];
$fcontent[$j] = $content[$l];
}
}
}
}
for($j = 0; $j < $c; $j++) //검색된 문서들을 랭킹함
{
$n = 1 + log($fct[$j], 2);
$kk = $n * $m;
$kkk[$j] = $kk * $kk;
$kkkk = $kkkk+$kkk[$j];
$kkkkk[$j] = $n / sqrt($kkkk);
}
for($j = 0; $j < $c; $j++) // 랭킹된 결과 출력
{
if($c>6) // 5개 이상 출력 될 경우
{
for($j = 0; $j < 5; $j++)
{
$n = 1 + log($fct[$j], 2);
$kk = $n * $m;
$kkk = cos($kk);
echo "<tr><td width='47%' align='left'>";
echo $ftitle[$j];
echo "</td>";
echo "<td><a href='$url'>";
echo $furl[$j];
echo "</a></td></tr>";
echo "<tr><td colspan='2' >";
echo $fcontent[$j];
echo "</tr></td><tr><td>";
echo $kkkkk[$j];
echo "</tr></td><tr><td colspan='2' ><hr></tr></td>";
}
break;
}
else //5개 이하일 경우
{
$n = 1 + log($fct[$j], 2);
$kk = $n * $m;
$kkk = cos($kk);
echo "<tr><td width='47%' align='left'>";
echo $ftitle[$j];
echo "</td>";
echo "<td><a href='$url'>";
echo $furl[$j];
echo "</a></td></tr>";
echo "<tr><td colspan='2' >";
echo $fcontent[$j];
echo "</tr></td><tr><td>";
echo $kkkkk[$j];
echo "</tr></td><tr><td colspan='2' ><hr></tr></td>";
}}}
?>
</body>
</html>
실제 동작 화면입니다.
결론으로는
손으로 뉴스 100개를 일일히 넣는건 고난이었습니다...
왜 크롤러가 있는지 알게된 날이었습니다.