Scrapy-Redis打造分布式爬虫

前言

分布式爬虫,听起来很高端!
首先要明确一下什么是分布式?还有一个概念是集群。

分布式:一个业务分拆多个子业务,部署在不同的服务器上
集群:同一个业务,部署在多个服务器上

所以,分布式爬虫,就是将爬取任务拆分成多个子任务,分别部署在不同的服务器上。

最简单的一个子任务,就可以是一个request的请求。

但是,很快就会遇到一个数据同步的问题,就是比如我在10台机器上部署了爬虫,他们应该共享一个爬取队列

这个队列可以持久化下来,存到数据库中,但是这就会产生很频繁的IO操作。那么可以采用Redis,一个内存数据库,基于这样一个思路Scrapy-Redis就产生了!

Scrapy-Redis

所谓的Scrapy-Redis实际上就是替换了原先Scrapy框架中的一系列组件,使其能够适应分布式的环境。

这样每个爬虫都从Redis的request队列中获取一个爬取请求,并将新的请求加入到队列中,同时会有一个基于指纹的去重。

配置列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 修改scrapy默认的调度器为scrapy重写的调度器 启动从reids缓存读取队列调度爬虫
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# 调度状态持久化,不清理redis缓存,允许暂停/启动爬虫
SCHEDULER_PERSIST = True

# 请求调度使用优先队列(默认)
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderPriorityQueue'

# 请求调度使用FIFO队列
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderQueue'

# 请求调度使用LIFO队列
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderStack'

# 最大的空闲时间,避免分布式爬取得情况下爬虫被关闭
# 此设置只适用于SpiderQueue和SpiderStack
# 也是爬虫第一次启动时的等待时间(应为队列是空的)
#SCHEDULER_IDLE_BEFORE_CLOSE = 10

# 存储爬取到的item,一定要在所有的pipeline最后,即设定对应的数字大于其他pipeline
ITEM_PIPELINES = {
'RSpider.pipelines.BaseSpiderPipeline': 256,
'scrapy_redis.pipelines.RedisPipeline': 300
}

# 指定redis的地址和端口(可选,程序将使用默认的地址localhost:6379)
REDIS_HOST = 'localhost'
REDIS_PORT = 6378

# 声明redis的url地址(可选)
# 如果设置了这一项,则程序会有限采用此项设置,忽略REDIS_HOST 和 REDIS_PORT的设置
#REDIS_URL = 'redis://user:pass@hostname:9001'

改造一个分布式爬虫

基于Scrapy-Redis可以很快的将一个传统的爬虫,改造成一个分布式爬虫。

主要修改以下几个地方:

1.settings.py

1
2
3
4
5
6
7
# 增加关于Scrapy-Redis的配置
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER_PERSIST = True
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
LOG_LEVEL = 'INFO'

2.Spider.py

1
2
3
4
5
from scrapy_redis.spiders import RedisSpider
# 爬虫继承RedisSpider,并配置redis_key
class DoubanBookTop250Spider(RedisSpider):
name = "top250"
redis_key = "top250:start_urls"



运行结果

开了4个终端,模拟4台机器,同时运行爬虫

可以看到在共享一个队列,爬取豆瓣top250的图书信息,平均每隔终端爬60多个,相当于任务被分解了。

扩展

基于Scrapy-Redis可以有更好的爬虫思维。

将每隔爬虫的任务更加细分。

比如有一个Master爬虫,源源不断的产生Request,后面的多个Slave爬虫,就不断的去Redis中取这些请求进行爬取。