当前位置:嗨网首页>书籍在线阅读

06-索引页分片爬取

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

11.4.1 索引页分片爬取

我们的第一步是优化索引页爬取,使其尽可能更快。在开始之前,先来设置一些期望。假设爬虫爬取并发量是16,并且我们测量得到其与源网站服务器的延迟大约为0.25秒。此时得到的吞吐量最多为16 / 0.25 = 64页/秒。索引页数量为50000个详情页 / 每个索引页30个详情页链接 = 1667索引页。因此,我们期望索引页下载花费的时间大约为1667 / 64 = 26秒多一点。

让我们以第3章中名为 easy 的爬虫开始。先把执行垂直抓取的Rule注释掉( callback='parse_item' 的那个),因为现在只需要爬取索引页。

你可以在GitHub中获取到本书的全部代码。下载该代码,可以访问: `git clone https://github.com/scalingexcellence/scrapybook` 。 本章中的完整代码位于 `ch11` 目录当中。

如果我们在进行任何优化之前对 scrapy crawl 只爬取10个页面的情况进行计时,可以得到如下结果。

$ ls
properties scrapy.cfg
$ pwd
/root/book/ch11/properties
$ time scrapy crawl easy -s CLOSESPIDER_PAGECOUNT=10
...
DEBUG: Crawled (200) <GET ...index_00000.html> (referer: None)
DEBUG: Crawled (200) <GET ...index_00001.html> (referer: ...index_00000.
html)
...
real 0m4.099s

如果10个页面就花费了4秒时间,那么就不可能在26秒时间内完成1,700个页面。通过查看日志,我们发现每个页面都来自于前一个页面的下一页链接,也就是说在任意时刻都只有至多一个页面正在执行爬取。我们的有效并发为1。我们希望并行处理,得到想要的并发数量(16个并发请求)。我们将对索引分片,并允许一些额外的分片,以确保爬虫中的URL不会不足。我们将会把索引分为20个段。实际上,任何超过16的数值都能够增加速度,不过在超过20之后所得到的回报呈递减趋势。我们将通过如下表达式计算每个分片的起始索引ID。

>>> map(lambda x: 1667 * x / 20, range(20))
[0, 83, 166, 250, 333, 416, 500, ... 1166, 1250, 1333, 1416, 1500, 1583]

因此,我们使用如下代码设置 start_urls

start_urls = ['http://web:9312/properties/index_%05d.html' % id
       for id in map(lambda x: 1667 * x / 20, range(20))]

这可能和你的索引有很大的不同,因此我们没必要在此处实现得更漂亮。如果还设定了并发设置( CONCURRENT_REQUESTSCONCURRENT_REQUESTS_PER_DOMAIN )为16,那么当运行爬虫时,将会得到如下结果。

$ time scrapy crawl easy -s CONCURRENT_REQUESTS=16 -s CONCURRENT_
REQUESTS_PER_DOMAIN=16
...
real 0m32.344s

该结果已经与期望值非常接近了。我们的下载速度为 1667个页面 / 32秒 = 52个索引页/秒,这就意味着每秒可以生成52×30 = 1560个详情页URL。现在,可以将垂直抓取的 Rule 的注释取消掉,保存文件作为新爬虫分发。我们不需要对爬虫代码进行更多修改,这显示出我们即将开发的中间件的强大以及非侵入性。如果只使用开发服务器运行 scrapy crawl ,假设处理详情页的速度和索引页处理时一样快,那么它将花费不少于50000 / 52 = 16分钟时间完成爬取。

本节有两个关键内容。在学习完第10章之后,我们已经可以实现真正的工程。我们能够精确计算出系统期望得到的性能,并且确保在达到该性能之前不会停止(在合理范围内)。第二个要记住的重要事情是,由于索引页爬取提供了详情页,爬取的总吞吐量将会是其吞吐量的最小值。如果我们生成的URL比Scrapyd能够消费得更快,那么URL将会堆积在其队列当中。反过来,如果生成的URL太慢,Scrapyd将会拥有过剩的无法利用的能力。