Scheduler:
Scrapy改造了python本来的collection.deque(双向队列)形成了自己的Scrapy queue,但是Scrapy多个spider不能共享待爬取队列Scrapy queue,即Scrapy本身不支持爬虫分布式,scrapy-redis 的解决是把这个Scrapy queue换成redis数据库(也是指redis队列),从同一个redis-server存放要爬取的request,便能让多个spider去同一个数据库里读取 。

文章插图
Scrapy中跟“待爬队列”直接相关的就是调度器Scheduler,它负责对新的request进行入列操作(加入Scrapy queue),取出下一个要爬取的request(从Scrapy queue中取出)等操作 。它把待爬队列按照优先级建立了一个字典结构,然后根据request中的优先级,来决定该入哪个队列,出列时则按优先级较小的优先出列 。为了管理这个比较高级的队列字典,Scheduler需要提供一系列的方法 。但是原来的Scheduler已经无法使用,所以使用Scrapy-redis的scheduler组件 。
Duplication Filter:
Scrapy中用集合实现这个request去重功能,Scrapy中把已经发送的request指纹放入到一个集合中,把下一个request的指纹拿到集合中比对,如果该指纹存在于集合中,说明这个request发送过了,如果没有则继续操作 。
在scrapy-redis中去重是由Duplication Filter组件来实现的,它通过redis的set 不重复的特性,巧妙的实现了Duplication Filter去重 。scrapy-redis调度器从引擎接受request,将request的指纹存?redis的set检查是否重复,并将不重复的request push写?redis的 request queue 。
引擎请求request(Spider发出的)时,调度器从redis的request queue队列?里根据优先级pop 出?个request 返回给引擎,引擎将此request发给spider处理 。
Item Pipeline:
引擎将(Spider返回的)爬取到的Item给Item Pipeline,scrapy-redis 的Item Pipeline将爬取到的 Item 存?redis的 items queue 。
修改过Item Pipeline可以很方便的根据 key 从 items queue 提取item,从?实现items processes集 群 。
Base Spider:
不在使用scrapy原有的Spider类,重写的RedisSpider继承了Spider和RedisMixin这两个类,RedisMixin是用来从redis读取url的类 。
当我们生成一个Spider继承RedisSpider时,调用setup_redis函数,这个函数会去连接redis数据库,然后会设置signals(信号):
一个是当spider空闲时候的signal,会调用spider_idle函数,这个函数调用schedule_next_request函数,保证spider是一直活着的状态,并且抛出DontCloseSpider异常 。
一个是当抓到一个item时的signal,会调用item_scraped函数,这个函数会调用schedule_next_request函数,获取下一个request 。
Scrapy-redis架构:

文章插图
如上图所示,我们可以发现,scrapy-redis在scrapy的架构上增加了redis,与scrapy相差无几 。本质的区别就是,将scrapy的内置的去重的队列和待抓取的request队列换成了redis的集合 。就这一个小小的改动,就使得了scrapy-redis支持了分布式抓取 。
Scrapy-Redis分布式策略:
假设有四台电脑:windows 10、mac OS X、Ubuntu 16.04、centos 7.2,任意一台电脑都可以作为 Master端 或 Slaver端,比如:
--Master端(核心服务器) :使用 Windows 10,搭建一个Redis数据库,不负责爬取,只负责url指纹判重、Request的分配,以及数据的存储
--Slaver端(爬虫程序执行端) :使用 Mac OS X 、Ubuntu 16.04、CentOS 7.2,负责执行爬虫程序,运行过程中提交新的Request给Master

文章插图
首先Slaver端从Master端拿任务(Request、url)进行数据抓取,Slaver抓取数据的同时,产生新任务的Request便提交给 Master 处理;
Master端只有一个Redis数据库,负责将未处理的Request去重和任务分配,将处理后的Request加入待爬队列,并且存储爬取的数据 。
明白了原理之后我们就要入手程序了
Scrapy-Redis默认使用的就是这种策略,我们实现起来很简单,因为任务调度等工作Scrapy-Redis都已经帮我们做好了,我们只需要继承RedisSpider、指定redis_key就行了 。
将 scrapy 变成 scrapy-redis 的过程(前提是pip install scrapy-redis)
最简单的方式是使用 redis 替换机器内存,你只需要在 settings.py 中加上三代码,就能让你的爬虫变为分布式 。

文章插图
如果你现在运行你的爬虫,你可以在redis中看到出现了这两个key:
推荐阅读
- 谈谈茶馆的功能与茶馆文化
- 潮州壶的变革与突围
- 舒曼,问卜与求神 不如吃茶去
- 林冲与武松 林冲和武松的武功谁高
- 功夫茶具与功夫茶叶
- 三种不同风格的紫砂器浅析
- 茶文化与茶具有着不可磨灭的关系
- 紫砂器与茶文化的交融
- 梦到跟过世的老人一起生活 梦见与已故的老人睡同一张床
- 全面屏的一生之敌,华为与苹果为何还不妥协?
