Scrapy_redis在scrapy的基础上实现了更多,更强大的功能,具体体现在:reqeust去重,爬虫持久化,和轻松实现分布式.
- scrapy_redis是第三方的库,需要使用pip下载:
pip install scrapy_reids
Scrapy-redis提供了下面四种组件(components):(四种组件意味着这四个模块都要做相应的修改)
- Scheduler
- Duplication Filter
- Item Pipeline
- Base Spider
Scrapy_redis的工作流程
![]()
(1)设置去重组件,使用的是scrapy-redis的去重组件,而不是用scrapy框架的去重组件
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
(2)设置调度器,使用的是scrapy-redis重写的redis,而不是scrapy自带的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
(3)可以实现断点爬取,爬取进度不会丢失,会存储在redis数据库中,不会清楚redis的队列
SCHEDULER_PERSIST = True
(4)设置任务队列的模式(三选一)
- 是scrap-redis默认使用的队列模式,有自己的优先级.
SCHEDULER_QUEUE_CLASS="scrapy_redis.queue.SpiderPriorityQueue"- 是使用了队列的形式,任务先进先出.
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"- 是采用了栈的形式,任务先进后出.
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
(5)设置管道文件,实现这个管道,可以将爬虫端获取的item数据,同意保存在redis数据库中
'scrapy_redis.pipelines.RedisPipeline': 400,
(6)配置redis信息
- 指定要存储的redis数据库的主机IP
REDIS_HOST= '127.0.0.1'- 指定redis数据库主机的端口
REDIS_PORT= 6379
Scheduler:
Scrapy改造了python本来的collection.deque(双向队列)形成了自己的Scrapy queue,但是Scrapy多个spider不能共享待爬取队列Scrapy queue, 即Scrapy本身不支持爬虫分布式,scrapy-redis 的解决是把这个Scrapy queue换成redis数据库(也是指redis队列),从同一个redis-server存放要爬取的request,便能让多个spider去同一个数据库里读取。
Duplication Filter
Scrapy中用集合实现这个request去重功能,Scrapy中把已经发送的request指纹放入到一个集合中,把下一个request的指纹拿到集合中比对,如果该指纹存在于集合中,说明这个request发送过了,如果没有则继续操作。这个核心的判重功能是这样实现的:
def request_seen(self, request):
# 把请求转化为指纹
fp = self.request_fingerprint(request)
# 这就是判重的核心操作 ,self.fingerprints就是指纹集合
if fp in self.fingerprints:
return True #直接返回
self.fingerprints.add(fp) #如果不在,就添加进去指纹集合
if self.file:
self.file.write(fp + os.linesep)
Item Pipeline:
引擎将(Spider返回的)爬取到的Item给Item Pipeline,scrapy-redis 的Item Pipeline将爬取到的 Item 存⼊redis的 items queue。
Base Spider
不在使用scrapy原有的Spider类,重写的RedisSpider继承了Spider和RedisMixin这两个类,RedisMixin是用来从redis读取url的类。
当我们生成一个Spider继承RedisSpider时,调用setup_redis函数,这个函数会去连接redis数据库,然后会设置signals(信号)
clone github scrapy-redis源码文件
git clone https://github.com/rolando/scrapy-redis.git
- 注意: RedisSpider类 不需要写start_urls:
- scrapy-redis 一般直接写allowd_domains来指定需要爬取的域,也可以从在构造方法init()里动态定义爬虫爬取域范围(一般不用)。
- 必须指定redis_key,即启动爬虫的命令,参考格式:redis_key = 'myspider:start_urls'
- 根据指定的格式,start_urls将在 Master端的 redis-cli 里 lpush 到 Redis数据库里,RedisSpider 将在数据库里获取start_urls。
总结:
- 如果只是用到Redis的去重和保存功能,就选第一种;
- 如果要写分布式,则根据情况,选择第二种、第三种;
- 通常情况下,会选择用第三种方式编写深度聚焦爬虫。
网友评论