网络爬虫是按照一定的规则自动抓取万维网上信息的程序或脚本。网络爬虫是搜索引擎系统中非常重要的一部分。它负责从互联网上收集网页和信息。这些网页用于建立索引,为搜索引擎提供支持。它决定了整个引擎系统的内容是否丰富,信息是否及时,所以它的性能直接影响搜索引擎的效果。
网络爬虫程序的质量很大程度上反映了一个搜索引擎的质量。不信,你可以随便拿一个网站,通过各种搜索查看其页面的收录情况,爬虫的强弱基本上和搜索引擎的好坏成正比。
1.世界上最简单的爬行动物——三引用诗
我们来看一个最简单最简单的爬虫,用python写的,只需要三行。
导入请求URL=' http://www . cricode . com ' r=requests . get(URL)以上三行爬虫程序,就像下面三个引号一样,干脆利落。
是个好人,
你应该和你的女朋友吵架,
抱着一种失败的心态。
2.一个普通的爬虫程序
上面最简单的爬行动物,是不完整的,残疾的爬行动物。因为爬虫程序通常需要做的事情如下:
1)给定种子URL,爬虫爬下所有种子URL页面。
2)爬虫解析爬取的URL页面中的链接,放入要爬取的URL集合中。
3)重复步骤1、2,直到满足指定的条件。
因此,一只完整的爬行动物大概是这样的:
Import requests #用于从BS4抓取网页,ImportBeautiful Soup #用于解析网页seds=['http://www.hao123.com '#我们的seed' http://www.csdn.net 'http://www.cricode.com']sum=0 #我们设置终止条件如下:抓取到100000页时我不玩而sum 10000:if sum len(seds):r=requests。get(seds[sum])sum=sum 1 do _ save _ action(r)soup=美汤(r.content)。网址=汤。find _ all ('href ')//分析网页中的URL:seds。追加(URL) else: break 3。现在我们来挑毛病。
上面完整的爬虫,不到20行代码,相信你能找到20根茬。因为它有太多的缺点。以下逐一列举其n宗罪:
1)我们的任务是爬10000个网页。按照上面的程序,一个人在默默爬行。假设爬一个网页需要3秒,爬一万个网页需要3万秒。MGD,应该考虑启动多线程(池)一起抓取,或者采用分布式架构并发抓取网页。
2)种子URL和后来解析的URL都放在一个列表中,所以我们要设计一个更合理的数据结构来存储这些要抓取的URL,比如队列或者优先级队列。
3)我们对所有网站的网址一视同仁。其实应该区别对待。应该考虑大站好站优先的原则。
4)我们每次发出请求,总是根据url发出请求,这个过程会涉及到DNS解析,将url转换成ip地址。一个网站通常由成千上万个网址组成,我们可以考虑缓存这些网站域名的IP地址,避免每次都要进行费时费力的DNS请求。
5)解析完网页中的URL后,我们没有做任何重新处理,全部放入列表中进行抓取。其实可能有很多重复的环节,我们做了很多重复的工作。
6)… .
4.找了这么多茬,很有成就感。真正的问题来了。哪个比挖掘机好?
现在我们来逐一讨论一下上述故障中发现的一些问题的解决方法。
1)平行爬升问题
我们可以有多种方法来实现并行。
多线程或线程池模式下,爬虫程序在内部打开多个线程。同一台机器打开多个爬虫程序,这样我们就有n个以上的爬虫线程同时工作。可以大大减少时间。
另外,当我们要爬很多任务的时候,一台机器一个网点肯定是不够的,必须考虑分布式爬虫。常见的分布式架构有:Master——Slave架构、对等架构、混合架构等。
说到分布式架构,有很多问题需要我们考虑。我们需要分配任务,所有的爬行动物都需要交流合作,共同完成任务。不要重复抓取同一个网页。如果我们想公平公正地分配任务,我们需要考虑如何平衡负载。负载均衡,我们首先想到的是hash,比如根据网站的域名进行Hash。
负载均衡任务分配后,不要以为一切都好。一台机器死了怎么办?原本分配给哪个机器的任务被谁挂机了?或者有一天要增加几台机器的时候如何重新分配任务?
更好的解决方案是使用一致的哈希算法。
2)待爬取网页队列
如何对待要爬行的队列类似于操作系统如何调度进程。
不同的网站有不同的重要程度。因此,可以设计一个优先级队列来存储要爬取的网页链接。这样我们每次抓取的时候都优先抓取重要的网页。
当然,你也可以仿真操作系统的进程调度策略的多级反馈队列调度算法。
3)DNS缓存
为了避免每次都发起DNS查询,我们可以缓存DNS。DNS缓存当然是设计一个哈希表来存储现有的域名及其IP。
4)网页去重
说到网页去重,首先想到的就是垃圾邮件过滤。垃圾邮件过滤的经典解决方案是Bloom Filter。Bloom filter的原理简单来说就是构建一个大的比特数组,然后用多个哈希函数对同一个url进行哈希运算得到多个数字,然后将这些数字在比特数组中对应的位置设置为1。下次来一个url,也会用多个哈希函数哈希,得到多个数字。我们只需要判断位数组中的这些数是否对应全1。如果都是1,那么这个url已经出现了。这样就完成了url去重的问题。这种方法当然会有误差,只要误差在我们的容忍范围内,比如10000个网页,而我只爬了9999个,剩下的网页,谁管呢!
5)数据存储的问题
数据存储也是一个技术性很强的问题。在访问关系数据库、使用NoSQL或设计特定的存储文件格式方面,有很多文章可以做。
6)进程间通信
分布式爬虫离不开进程间的通信。我们可以按照指定的数据格式进行数据交互,完成进程间的通信。
7)……
说了这么多废话,真正的问题来了。问题不是哪个比挖掘机好。但是这些东西怎么实现啊!)
在实现的过程中,你会发现我们要考虑的不仅仅是以上这些。纸上得来的东西很浅,知道了还得去实践!
审核编辑:李倩
标签:网页爬虫问题