Scrapy-Redis的主要组件
基于Redis的特性,Scrapy-Redis扩展了如下组件。
1. Scheduler(调度器)
Scrapy框架改造了Python本来的双向队列,形成了自己的Scrapy Queue,但是Scrapy的多个爬虫不能共用待爬取队列Scrapy Queue,无法支持分布式爬取。Scrapy-Redis则把Scrapy Queue换成了Redis数据库,由一个Redis数据库统一存放要爬取的请求,便能让多个爬虫到同一个数据库里面读取。
在Scrapy框架中,跟“待爬队列”直接相关的就是调度器Scheduler,它负责将新的请求添加到队列(加入Scrapy Queue),以及取出下一个要爬取的请求(从Scrapy Queue中取出)。Scheduler将待爬取队列按照优先级存储在一个字典结构内,比如:
{
优先级0 : 队列0
优先级1 : 队列1
优先级2 : 队列2
}
在添加请求时,根据请求的优先级(访问priority属性)来决定该入哪个队列,出队列时则按优先级较小的优先出列。为了管理这个高级的队列字典,Scheduler需要提供一系列的方法,Scrapy原来的Scheduler已经无法使用,换成使用Scrapy-Redis的Scheduler组件。
2. Duplication Filter(去重组件)
Scrapy中使用集合实现请求的去重功能,它会把已经发送出去的请求指纹(请求的特征值)放到一个集合中,然后把下一个请求指纹拿到集合中比对。如果该指纹存在于集合中,则说明这个请求发送过了;如果不存在,则继续操作。
Scrapy-Redis中的去重是由Duplication Filter组件实现的,该组件利用Redis中set集合不重复的特性,巧妙地实现了这个功能。首先Scrapy-Redis调度器接收引擎递过来的请求,然后将这个请求指纹存入set集合中检查是否重复,并把不重复的请求加入到Redis的请求队列中。
3. Item Pipeline(管道)
当爬虫爬取到Item数据时,引擎会把Item数据交给Item Pipeline(管道),而管道再把Item数据保存到Redis数据库的Item队列中。
Scrapy-Redis对Item Pipeline组件进行了修改,它可以很方便地根据键(Key)从Item队列中提取Item,从而实现Items Processes集群。
4. Base Spiders(爬虫)
Scrapy-Redis中的爬虫,不再使用Scrapy原有的Spider类表示,而是使用重写的RedisSpider类,该类继承了Spider和RedisMixin这两个类,其中RedisMixin是用来从Redis读取URL的类。
当我们生成一个Spider继承自RedisSpider时,调用setup_redis函数,这个函数会去连接Redis数据库,当满足一定条件时,会设置如下两个信号:
一个是爬虫端(可以是多个机器)空闲时候的信号。这个信号交给引擎,由引擎去判断爬虫当下是否处于空闲状态。如果是空闲状态,就会调用spider_idle函数,这个函数调用schedule_next_request函数调度请求交给爬虫,保证爬虫一直是活动的状态,并且抛出DontCloseSpider异常。
另一个是抓到一个Item时的信号,这个信号依然会交给引擎判断,如果检测到确实抓取到Item,则会调用item_scraped函数,该函数会调用schedule_next_request函数获取下一个请求。