蛙蛙推荐:谈谈网络爬虫设计中的问题

蛙蛙推荐:谈谈网络爬虫设计中的问题

网络蜘蛛现在开源的已经有好几个了,LarbinNutchHeritrix都各有用户之地,要做一个自己的爬虫要解决好多个问题,比如调度算法、更新策略、分布式存储等,我们来一一看一下。

一个爬虫要做的事主要有以下这些
  1. 从一个网页入口,分析链接,一层一层的遍历,或者从一组网页入口,或者从一个rss源列表开始爬rss;
  2. 获取每个页面的源码保存在磁盘或者数据库里;
  3. 遍历抓下来的网页进行处理,比如提取正文,消重等;
  4. 根据用途把处理后的文本进行索引、分类、聚类等操作。
以上是个人理解哦,呵呵。这些过程中,大约有如下问题

如何获取网页源或者RSS源?
如果是一般的爬虫的话,就是给几个入口页面,然后顺着超链接以遍历图的算法一个页面一个页面的爬,这种情况网页源很少,可以选择从hao123等网址大全的网站为入口开始爬。如果做垂直搜索的话就人工去收集一些这个行业的网站,形成一个列表,从这个列表开始爬。如果是爬RSS的话,需要先收集RSS源,现在大的门户的新闻频道和主流的博客系统都有rss的功能,可以先爬一遍网站,找出rss的链接,要获取每个链接的内容,分析是否是rss格式,如果是就把这个链接保存到rss源数据库里,以后就专门爬这个rss源的rss。还有一种就是人工来整理,一般blog的rss都是有规律的,主域名跟一个用户名后面再跟上一个rss的固定页面,比如http://www.abc.com/user1/rss.xml,这样就弄一个用户字典,拼接rss地址,然后用程序去探测是否有这个页面来整理出每个网站的rss源。整理出rss源后再人工设置rss源的权重及刷新时间间隔等。

如果源页面很多,如何用多线程去有效的调度处理,而不会互相等待或者重复处理?
如果现在有500万个页面要去爬,肯定要用多线程或者分布式多进程去处理了。可以把页面进行水平分割,每个线程处理一段儿,这样每个线程之间不需要同步,各自处理各自的就行了。比如给这500W个页面分配一个自增ID,2个线程的话就让第一个线程去爬1,3,5的网页,第二个线程去爬2,4,6的网页,这样做多个线程间基本上能均衡,而且不会相互等待,而且不会重复处理,也不会拉掉网页。每个线程一次取出1w个页面,并记录最高的源页面ID号,处理完这一批后再从数据库里提取大于这个源页面ID号的下1W个页面,直到抓取完本线程要处理的所有页面。1w这个值根据机器的内存可做适当的调整。为了防止抓了半截儿死机,所以要支持断点续抓,要为每个线程的处理进度保存状态,每取一批网页都要记录本线程最大的网页ID,记录到数据库里,进程重启后可以读取这个ID,接着抓后面的页面。

如何尽量的利用CPU,尽量的不让线程处于等待、休眠、阻塞等空闲状态?而且要尽量用少的线程以减少上下文切换。
爬虫有两个地方需要IO操作,抓网页的时候需要通过网卡访问网络,抓到网页后要把内容写到磁盘或者数据库里。所以这两个部分要用异步IO操作,这样可以不用线程阻塞在那里等待网页抓过来或者写完磁盘文件,网卡和硬盘都支持内存直接读取,大量的IO操作会在硬件驱动的队列里排队,而不消耗任何CPU。.net的异步操作使用了线程池,不用自己频繁的创建和销毁线程,减少了开销,所以线程模型不用考虑,IO模型也不用考虑,.net的异步IO操作直接使用了完成端口,很高效了,内存模型也不需要考虑,整个抓取过程各线程不需要访问共享资源,除了数据库里的源页面,各管各的,而且也是每个线程分段处理,可以实现无锁编程。

如何不采集重复的网页?
去重可以使用king总监的布隆过滤器,每个线程使用一个bitarray,里面保存本批源页面上次抓取的页面的哈希值情况,抓取下来的源页面分析链接后,去这个bitarray里判断以前有没有抓过这个页面,没有的话就抓下来,抓过的话就不管了。假设一个源页面有30个链接把,一批10W个源页面,300w个链接的bitarray应该也不会占太大内存。所以有个五六个线程同时处理也是没问题的。

抓下来的页面更快的保存?保存到分布式文件系统还是保存在数据库里?
如果保存到磁盘,可以每个域名创建一个文件夹,凡是这个网站的页面都放到这个文件夹下,只要文件名不一样,就不会出现冲突。如果把页面保存到磁盘,数据库有自己的一套锁管理机制,直接用bulk copy放数据库就行了。一般频繁的写磁盘可能会引起CPU过高,而频繁的写数据库CPU还好一些。而且sqlserver2008支持filestream类型的字段,在保存大文本字段的时候有很好的性能,并且还能使用数据库的API来访问。所以我觉得如果没有GFS那样高效成熟的分布式文件系统的话还不如存sqlserver里面呢。

如何有效的根据网页的更新频率来调整爬虫的采集时间间隔?
做爬虫要了解一些HTTP协议,如果要抓的网页支持Last-Modified或者ETag头,我们可以先发个head请求来试探这个页面有没有变化来决定是否要重新抓取,但是好多网站根本就不支持这个东西,所以让爬虫也很费劲,让自己的网站也会损失更多的性能。这样我们就要自己去标注每个源页面的更新时间间隔及权重,再根据这两个值去用一定的算法制定蜘蛛的更新策略。

采集下来的数据做什么用?
可以抓取一个行业的网站,在本地进行分词和索引,做成垂直搜索引擎。可以用一定的训练算法对抓取下来的页面进行自动分类,做成新闻门户。也可以用死小风行的文本相似度算法处理后进行文本聚类处理。

如何不影响对方网站的性能?
现在好多网站都被爬虫爬怕了,因为有些蜘蛛弄住一个网站可劲儿的爬,爬的人家网站的正常用户都无法访问了。所以好多站长想了好多办法来对付爬虫,所以我们写爬虫也要遵循机器人协议,控制单位时间内对一个网站的访问量。

其它问题:
http://notes.zhourenjian.com/whizznotes/xhtml/4308.html
posted @ 2008-04-19 19:41  蛙蛙王子  Views(10477)  Comments(18Edit  收藏  举报