没有看过什么搜索引擎原理的书,最近写了一些搜索newsmth的脚本,根据经验,我想象中的搜索引擎的几个要素大抵是像下面这样的:
一、搜索引擎公司肯定是有很多分布式文件的高性能服务器的,至少有两类,一类是用来定时抓取各个网站的网页内容,另一类是用来提供给用户去搜索的。那些Google快照、百度快照就是搜索引擎公司抓取了网页内容的证据,即使原始的网页被删掉,快照还是依然存在的。
二、为什么要抓取网页内容?那首先知道,搜索引擎凭什么知道这个网页含有要搜索的关键字?还不是挨个打开去看的?世界上的网站千千万,互联网上的网页万万千,如果直到用户输入关键字时才去打开所有的网页去查找,那是不是太慢了?计算机的性能不是瓶颈,网络I/O才是瓶颈,如果挨个打开,恐怕等一两个小时也搜索不完的。所以,需要抓取网页内容保存在计算机本地,这样查找起来才会很快。
当然,Google和百度也不是万能的,它们不可能抓取所有的网页,它们应该是按照一定的算法(活跃度、访问数量、权值)。如果有些网站不允许爬虫去抓取,Google等搜索引擎也会遵守规则的(百度可能除外)。
三、即使保存在本地,那保存的文件也是很多的。这时候应该就有建立索引或者其他更适合查找的东西了。
最后谈一下,我写的搜索newsmth的大概原理:
由于我的计算机只是普通的家用计算机,网络宽带只有1M,所以网络I/O是我程序最大的瓶颈。因此,如果需要打开很多网页或者下载文件的,我尽量使用多线程。多线程是很惊人的,在速度上有了若干个数量级上的飞跃。我的程序是在web下打开web完成的,我想telnet方式的速度还会更快。
1、遍历分区(http://www.newsmth.net/bbssec.php),枚举(包括对二级目录的递归枚举)得到newsmth上的所有对搜索可能有用的版面信息(版面id、版面名称和最大文章数),将其保存到本地的board.txt文件里。这相当于我的索引吧,第二次搜索的时侯就不需要再去遍历了。当然,版面的最大文章数是会变化的,可以定时更新,或者强制更新。
2、搜索newsmth全站站内某ID发表的、标题含有某些关键字的、在多少天内发表的帖子是很容易的。全站内,分解下来不就是各个版面的版内文章搜索结果的组合么?
我的灵感来自诸如这样的版内文章搜索链接:http://www.newsmth.net/bbsbfind.php?board=FamilyLife。newsmth的搜索版面文章的url类似于:http://www.newsmth.net/bbsbfind.php?q=1&board=FamilyLife&title=&title2=&title3=&userid=&dt=7&mg=on&ag=on&og=on,观察一下,可以发现填好各种参数(board、title、title2、title3、userid、dt、mg、ag、og)就可以了。其中,board就是版面名称,可以自己填好,如果是遍历全站时我们可以从board.txt得到。
将各个参数填好,我们去取版内文章搜索结果的内容(只有一个页面),将其解析填到自己的全站搜索结果页面即可。
我想,这种方法是常规的搜索newsmth最方便快速方法了,速度可以跟Google媲美啊,呵呵。
版内文章搜索
AND
天以内
版内文章搜索
3、搜索帖子内含有特定关键字的方法。
(1)读取boards.txt,根据(版面名称、版面id和最大文章数)遍历各个版面的page,获得各个版面的帖子url,存于本地,一个版面的所有url存成一个txt文件。全站一共有近500个版面,有些版面的帖子都是几万的,估计帖子数应该有近百万吧。我开了500个线程,发现还是有点慢,后来我就开了1000个线程,天网防火墙不断提示我newsmth不断向我发送数据,问我是否屏蔽,我直接把天网关掉了。说得有些含糊,不过大概原理就是如此。为了节约时间,如果仅查询某个版面内的,就直接多线程遍历那个版面好了,单独一个版面还是很快的。
写程序时,要注意多线程写文件的互斥,同时也要注意减少写文件的次数,不要写得太频繁,否则程序性能就不太好了,电脑也有可能吃不消。
(2)如果我是专门做一个搜索水木网站的网站,我会再开一个多线程,将各个帖子的内容抓到本地来,每个文章弄成一行,这样搜索速度会更快。我怕伤了我的硬盘,没有做这个。
(3)如果做了步骤(2),则读取保存有网页url的文件,逐行查找即可。如果没有做步骤(2),则需要挨个打开网页去查找了,这里也是使用到了多线程、写文件互斥,速度还挺快。
4、其他应用:
(1)查找马甲:文字往往能不经意间出卖一个人。根据某些ID常用的口吻,如有些人常喜欢写“laf”、”之类的,以这些关键字搜索帖子,再加上一定的条件(IP、发帖时间等),就很容易找到马甲啦。
(2)精华文章下载:根据记号来,一般是含有m、g之类的。
(3)照片下载:到Myphoto版,从记号含有m的文章中获得附件的链接,从而下载。俺曾经下载了近5G的照片,发现硬盘后来就出问题了,赶紧删掉照片,对硬盘做了简单的修复。
(4)文风分析:搜索某ID全站的文章(可以限制在一定字数之上,如500字,也防止了灌水文章),统计其使用频率最长的词语是啥。这可能使用到了分词技术或者别的,我只是想想。
如果再抄上一点搜索引擎理论,具体实践和实践效果写得详细一点,再加上一点看起来很高深的算法(例如索引之类的),抓上几个图,做一下性能的比较。嗯,我觉得都可以写成一篇论文了。呵呵,我胡说八道几句罢了,我只是写了几行代码,哪里就跟搜索引擎沾上边了?大家不要当真。
感谢:嗯,感谢baileifirist,本来我只做了2的,是他提出搜索含有关键字的帖子内容,我才去做3的,第一次真正使用到了多线程,让我使用Python又上了一个新台阶。其次感谢westgua,他不说查找马甲,恐怕我也懒得写下去了。
最后声明:最近newsmth频繁要重启,希望与我无关。我只是练习一下代码而已,没有啥特殊的事的话,以后不再去爬newsmth了。
...