首页 > 代码库 > 高效爬虫实战经典案例

高效爬虫实战经典案例

最近,我接到一个任务,具体来说就是:

使用百度来搜索30万关键词,把搜索结果中出现的网站链接全部储存下来。

我们来计算一下,30万关键词,每个关键词百度会给出75个页面,就是2250万个网页的爬虫量。考虑到延时等在内,每秒平均处理一个页面,就需要22500000/(24*3600) = 260天时间,我们用并行处理,十个进程,并行,也需要26天,这简直不可接受

我的改进之路:

首先,考虑多线程,python的多线程不是那么强势,我最开始是这么做的:每一个关键词的75个url的处理,把处理出来的数据放在mysql里面,使用多线程,当处理完后,再来处理下一个关键词,这个程序我的实际运行效率是一个单词大概30秒,也就是一天能处理三千多个单词,程序要运行一百天

然后,我觉得爬每个关键词的结果放在mysql里面,因为要避免放入重复的数据,所以我每次都要判断是否存在,这个步骤很费时间,我想到了redis,并做了实验,由于redis在内存中,而且是键值对的形式,我把爬到的网址当作键,就不用检查是否重复了,并且我计算了一下,假设我最终得到500万不同的网址,每个网址的存储花费30Byte,也才5000000*30/1024 = 146484KB = 143MB,内存完全能够放下,至此,存储方面就可以不用怎么优化了

接着,我们发现一个问题,把每个关键词的75个url作为一个多线程模块,运行完之后,才处理下一个关键词,那么必然有一部分时间的并行量不够,这浪费了,所以我想把所有的单词的url都放入多线程,设置最大并行线程数,但是这样的问题就是不知道某个单词是否已经处理完毕,所以我进行预处理,专门使用一个程序来产生所有的url,并存入txt里面,这一步我也计算过,容量没问题,之后把整个url_list进行多线程操作,就快多了

还有,我发现百度的搜索页面可以一次显示50条信息,而不是最初的十条,这样,我的页面数量瞬间减少到了五分之一,又是一大进步。

同时,我研究了爬取的速度绝对是受网速影响很大的,比如,1MB/S,那么每秒最多处理1MB的数据,所以这个时候,使用Gzip对网页进行压缩,就能大大增加每秒可以下载的网页数目,增加了爬虫效率。

最终结果:

我使用预处理,得到了四百八十多万url,然后,20分钟,处理了28000条,我们算一下,每分钟处理一千四百个url,那么,我们所需时间为:4800000/(24*60*1400) = 2.3天,而且还没有用到多进程,比起最开始的十个进程并行,还需要26天,时间减少到了百分之一不到,真的很爽

高效爬虫实战经典案例