如何创建自己的搜索引擎

Author: 翁建元 Date: 2001年 7期

?牐牨嘈葱〉乃阉饕媸导噬戏浅<虻ィ恍醇感蠵erl程序就可以把你自己的搜索引擎加到你的网点上。你所连的服务器必须运行UNIX系统,而且你要具有安装CGI脚本的能力。
  ?牐犚弧⑻岢鲆桓鏊惴?
  ?牐牬唇ㄒ桓龅剐蛩饕ɑ虺频剐蛩饕募?。这是一个文字表单,非常像书末尾部分的索引。假定我们有一个非常简单的网站,它只包含两页,如下所示:
  ?牐爋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比唬飧鲂∷阉饕婊褂胁簧傩枰慕牡胤剑侵皇潜喑痰奈侍饬恕?