如何创建自己的搜索引擎
?牐犚弧⑻岢鲆桓鏊惴?
?牐牬唇ㄒ桓龅剐蛩饕ɑ虺频剐蛩饕募?。这是一个文字表单,非常像书末尾部分的索引。假定我们有一个非常简单的网站,它只包含两页,如下所示:
?牐爋ne.html:??
?牐?<html><head>
?牐?<title>Doc One</title>
?牐?</head><body>
?牐?<p>Here document one.
?牐?</body></html>
?牐爐wo.html:??
?牐?<html><head>
?牐?<title>Doc Two</title>
?牐?</head><body>
?牐?<p>Here another document.
?牐?</body></html>
?牐犖硕源送憬兴饕颐切枰闪礁霰淼ァJ紫龋颐墙扛鲆趁娼斜嗪牛⒘谐雒恳车谋晏夂蚒RL。这样,以后我们就可以拿数字来代表页面,会省出不少空间。
?牐?1 => /one.html,“Doc One”
?牐?2 => /two.html,“Doc Two”
?牐犗乱徊剑颐峭ü谐雒扛鲎旨捌渌诘奈募瓷傻剐蛩饕?
?牐燼nother=>2
?牐燿oc=>1,2
?牐燿ocument=>1,2
?牐爃ere=>2
?牐爄s=>1,2
?牐爋ne=>1
?牐爐his=>1
?牐爐wo=>2
?牐犚胧迪炙阉鳎诘剐蛩饕胁槌瞿阋业淖郑缓蟛榭凑飧鲎趾竺媪谐龅耐场5蹦阆胨阉鳌癶ere”这个字时,我们的脚本将在倒序索引中查找“here”,得到“2”,再去看“2”代表的网页,并把关于此文件的信息以链接的形式显示出来??
?牐?<a href=“/two.html”>Doc Two</a>
?牐犕绻慵肓礁鲎郑疟窘蚜礁鲎侄疾檎乙槐椋⑶叶剂谐霭蚜礁鲎侄及谀诘耐场?
?牐牰⒕龆ㄊ萁峁?
?牐牻剐蛩饕嬖谄胀ǖ奈募校⑶矣胓rep对它进行搜索来查找文字并不困难。因为索引比整个网点要小,所以此方法比用find和grep来搜索整个网点要有所进步。
?牐犖颐怯肈BM文件,当网页表单和索引文件中只含有(name=>value)类型的记录时,可以很容易就将它们在DBM文件的字符串中定位。用Perl编写的例索引如下所示:
?牐?%dbm =( ??
?牐牐?-1' => '<a href=“/one.html”>Doc One</a>',
?牐牐?-2' => '<a href=“/two.html”>Doc Two</a>',
?牐牐?another' => '-2',
?牐牐?doc' => '-1-2',
?牐牐?document' => '-1-2',
?牐牐?here' => '-2',
?牐牐?is' => '-1-2',
?牐牐?one' => '-1',
?牐牐?this' => '-1',
?牐牐?two' => '-2'
?牐牐?;?牔?
?牐犎⒋唇ㄒ桓鏊饕募?
?牐犗衷谖颐且嗔礁鼋疟荆憾寥∧阃旧系乃形募痛唇ǖ剐蛩饕ㄋ饕募┑拇耄约安檎矣没г诓檎冶碇惺淙氲淖值腃GI脚本。我们先来写索引文件。
?牐犑紫龋颐谴蚩娲⒌剐蛩饕腄BM文件。我将使用Berkeley DB来完成,这样打开索引文件:
?牐爑se DB_File??
?牐燿bmopen(%db,“search_index.db”, 0644) or die“dbmopen: $!”;??
?牐牭比唬赨NIX中查找文件的最简单的方法是利用UNIX find命令。
?牐爋pen(FILES, “find . -name '*.html' -print|”) or die“open for find: $!”;
?牐犖颐侵鸶龃蚩狧TML并把它们的内容放在一个变量中:
?牐爉y $filename;??
?牐爓hile(defined($filename = <FILES>))
?牐爗?牐? ??
?牐爌rint “indexing $filename”;??
?牐燾hop $filename;??
?牐爋pen(HTML, $filename) or do{warn“open $filename: $!”; next;};?? ?牔?
?牐爉y $html = join('', <HTML>);?牔?
?牐燾lose HTML;??
?牐犎缓笥霉嬖虮泶锸饺〕霰晏獠⒃谕潮淼ブ形艘辰ㄒ桓鋈肟讦?
?牐爉y ($title) =($html =~ /<title>([^<]*)/i);?牔?
?牐?$title = $filename if(!defined $title);?牔?
?牐?$db{--$fileno} = “<a href=\”$filename\“>$title</a>”;??
?牐犗衷谖颐且谐鐾成纤械淖郑紫任颐侨サ鬑TML标签:
?牐?$html=~s/<[^>]+>//g;??
?牐犎绻颐堑乃阉鞫源笮⌒床幻舾校敲窗阉形淖执娉赏淖痔褰蚧檠衷诎盐募蓟怀尚⌒醋痔澹?
?牐?$html=~ tr/A-Z/a-z/;??
?牐犗旅妫颐且盐募兴凶侄剂谐觯?
?牐爉y@words=($html=~/ \w+/g);?牔?
?牐犠詈螅颐前颜飧鲎旨尤氲剐蛩饕募邢嘤Φ男校繁M桓鲎置挥兴饕奖椋?
?牐爉y $last = “”;??
?牐爁or (sort @words){?? ??
?牐爊ext if($_ eq $last);?牔?
?牐?$last = $_;??
?牐?$db{$_} = defined $db{$_} ? $db{$_}.$fileno: $fileno;}?牓?
?牐牷旧暇褪钦庋馐钦鼋疟尽5蹦阍谕闵显诵兴保嵩谀阃愕母卟隳柯贾猩梢桓雒皊earch_index.db”的文件。这个文件包含有你网点上所有字的索引。
?牐犓摹⒋唇ㄋ阉饔玫腃GI
?牐犖颐且延幸桓鏊饕衷诟每悸侨糜没?使用它。我将执行一次简单的搜索,寻找包含用户输入的所有字的网页。搜索表非常简单:
?牐?<form action=“/search.cgi”>
?牐?<p><input name=s><input type=submit value=“Search”>
?牐?</form>
?牐爏earch.cgi读取表单变量并将它剖析成字:
?牐爉y $query = $ENV{'QUERY_STRING'};?牔?
?牐?$query =~ s/s=//;??
?牐?$query =~ s/%?焄0-9a-fA-F]{2}//g;??
?牐爉y@words =($query =~ /\w+/g);?牔?
?牐犗旅妫蚩剐蛩饕? DBM文件:
?牐爑se DB_File;??
?牐燿bmopen(%db,“search_index.db”,0);?牔?
?牐犖颐侵葱胁檠牟呗允俏扛鱿喙匚募A粢桓黾剖鳌?
?牐爉y %counters;??
?牐爉y $word;??
?牐爁or $word (@words){?? ??
?牐爉y $pages = $db{lc $word};?牔?
?牐爉y $page;??
?牐爁or $page ($pages =~ /(-\d)+/g){?? ??
?牐?$counters{$page}++;}}?牓牓?
?牐犎绻桓鑫募恳檎业淖郑募剖髟诿看窝肥倍荚黾?1,所以它的值将和要查找的字数相等。下面的脚本找出那些文件并显示出来:
?牐爁or $page (sort keys %counters){?? ??
?牐爄f($counters?焮$page}==scalar(@words)){?牐? ??
?牐爉y $href = $db{$page};?牔?
?牐爌rint“$href<br>”;}}?牓牓?
?牐犝饩涂梢粤恕5比唬飧鲂∷阉饕婊褂胁簧傩枰慕牡胤剑侵皇潜喑痰奈侍饬恕?