本文链接:http://blog.csdn.net/u012150179/article/details/38091411
一 scrapy-redis实现分布式爬取分析
所谓的scrapy-redis实际上就是scrapy+redis当中对redis的操作採用redis-pyclient。这里的redis的作用以及在scrapy-redis的方向我在自己fork的repository(链接:https://github.com/younghz/scrapy-redis)已经做了翻译(README.rst)。
在前面一篇文章中我已经借助两篇相关文章分析了使用redis实现爬虫分布式的中心。
归结起来就是:全部爬虫获取到的url(request)都放到一个redis queue中,而且全部爬虫都从单个redis queue中获取request(url)。
scrapy-redis已经非常长时间没有更新,怎样是它兼容更新版本号的scrapy我在博文(链接:http://blog.csdn.net/u012150179/article/details/38087661)中也已经说明,后期我可能会用较新版本号的scrapr接口重写scrapy-redis。
二 分布式爬取实现
1. 对scrapy-redis中自带example的分析
在库的README中已经对example的使用做了说明,可是初步接触时执行example中的spider会存在非常多疑问。比方,分布式体如今哪?是通过那几方面实现的?其次,在执行结果中非常难发现分布式的影子。感觉就像两个spider在自己爬自己的东西。
对于第一种疑问。我在翻译和标注scrapy-redis中settings.py已经做了说明。而第二中疑问也是实现2中自己的example所要做的。
2. 更清晰验证scrapy-redis实现分布式的思路与编码实现。
(1)思路
实现两个爬虫,定义爬虫A爬取dmoz.com的关键词bussiness下的全部链接(通过start_urls设定)。
爬虫B爬取game下的全部链接。观察二者同一时候执行时爬取链接的url,是各自范围的url还是二者的交集。这样因为二者定义的爬取范围是不一致的。通过爬取现象能够得出结果。
(2)实现
代码放在了github的repo中(https://github.com/younghz/scrapy-redis/)。
为了易于观察,设置DEPTH_LIMIT为1。
(3)现象与分析
现象:能够发现。二者是首先同一时候爬取单个关键词下的链接(首先爬取哪一个取决与先执行爬虫的start_urls)。完成后进而爬取还有一个关键词下链接。
分析:通过同一时候爬取单个关键词能够说明两个爬虫是同一时候被调度的,这就是爬虫的分布式。
而且爬虫默认是广度优先搜索的。爬取的过程例如以下:
i)首先执行爬虫A(B同理),爬虫引擎请求spider A中start_urls中的链接并交割调度器。进而引擎向调度器请求爬取的url并交给下载器下载,下载后的response交给spider,spider依据定义的rules得到链接,继续通过引擎交给调度器。(这一系列过程可查看scrapy架构)。
当中调度器scheduler中request(url)顺序是redis queue实现的,也就是将request(url)push到queue中。请求时pop出来。
ii)进而启动B,同理B的start_urls首先交给了调度器(注意和A中的调度器是同一个),而B的引擎请求爬取url时,调度器调度给B下载的url还是A中没下载完毕的url(默认的调度方式是先调度返回的url,而且是广度优先的)。这是A和B同一时候下载A中未完毕链接,待完毕后。同一时候下载B的要求链接。
iii)问题:上述ii中的调度方式是如何实现的?
在scrapy-redis中默认使用的是SpiderPriorityQueue方式。这是由sorted set实现的一种非FIFO、LIFO方式。
3. 细节分析与注意点
每次运行又一次爬取。应该将redis中存储的数据清空,否则影响爬取现象。
4. 其他
前者是由后者经由函数make_request_from_url实现,而且这个过程由spider完毕。
spider会返回(return、yield)request给scrapy引擎进而交割调度器。url也是在spider中定义或由spider获取的。
spider不同于crawler。crawler包括spider。scrapy的架构就是crawler。spider作用为:提供start_url,依据下载到的response分析获取想要的内容,继续提取url等。
原创,本文链接:http://blog.csdn.net/u012150179/article/details/38091411