前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫课堂(二十六)|使用scrapy-redis框架实现分布式爬虫(1)

爬虫课堂(二十六)|使用scrapy-redis框架实现分布式爬虫(1)

作者头像
黄小怪
发布2018-05-21 17:39:47
1.3K0
发布2018-05-21 17:39:47
举报
文章被收录于专栏:小怪聊职场小怪聊职场

到了讲scrapy-redis框架的时候啦,在讲它之前先提出三个问题:

  1. 我们要使用分布式,那么分布式有什么优点?
  2. Scrapy不支持分布式,是为什么?
  3. 如果要使Scrapy支持分布式,需要解决哪些问题?
  4. scrapy-redis是怎么解决这些问题的?

接下来,我们逐个回答:

  1. 分布式的主要优点包括如下两种: 1)充分利用多机器的宽带加速爬取。 2)充分利用多机的IP加速爬取速度。
  2. 爬虫课堂(十六)|Scrapy框架结构及工作原理章节中,我们已经讲解过Scrapy运行流程,如下图26-1所示: 1)当爬虫(Spider)要爬取某URL地址的页面时,使用该URL初始化Request对象提交给引擎(Scrapy Engine),并设置回调函数。 2)Request对象进入调度器(Scheduler)按某种算法进行排队,之后的每个时刻调度器将其出列,送往下载器。

在Scrapy中,以上的流程都是在单机操作,其他服务器是无法从现在的Scheduler中取出requests任务队列,另外这块的去重操作也是在当前服务器的内存中进行,这就导致Scrapy不支持分布式。

图26-1 Scrapy架构图

  1. 基于上面的分析,我们知道要使Scrapy支持分布式,那么就需要解决三个问题: 1)requests队列需要集中管理。 2)去重逻辑也需要集中管理。 3)保持数据逻辑也需要集中管理。
  2. scrapy-redis是怎么解决这些问题的? 我们先进入scrapy-redis的GitHub页面https://github.com/rmax/scrapy-redis,它在Usage明确说明了需要设置的地方:
代码语言:javascript
复制
# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# Default requests serializer is pickle, but it can be changed to any module
# with loads and dumps functions. Note that pickle is not compatible between
# python versions.
# Caveat: In python 3.x, the serializer must return strings keys and support
# bytes as values. Because of this reason the json or msgpack module will not
# work by default. In python 2.x there is no such issue and you can use
# 'json' or 'msgpack' as serializers.
#SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"

# Don't cleanup redis queues, allows to pause/resume crawls.
#SCHEDULER_PERSIST = True

# Schedule requests using a priority queue. (default)
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'

# Alternative queues.
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'

# Max idle time to prevent the spider from being closed when distributed crawling.
# This only works if queue class is SpiderQueue or SpiderStack,
# and may also block the same time when your spider start at the first time (because the queue is empty).
#SCHEDULER_IDLE_BEFORE_CLOSE = 10

# Store scraped item in redis for post-processing.
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 300
}

# The item pipeline serializes and stores the items in this redis key.
#REDIS_ITEMS_KEY = '%(spider)s:items'

# The items serializer is by default ScrapyJSONEncoder. You can use any
# importable path to a callable object.
#REDIS_ITEMS_SERIALIZER = 'json.dumps'

# Specify the host and port to use when connecting to Redis (optional).
#REDIS_HOST = 'localhost'
#REDIS_PORT = 6379

# Specify the full Redis URL for connecting (optional).
# If set, this takes precedence over the REDIS_HOST and REDIS_PORT settings.
#REDIS_URL = 'redis://user:pass@hostname:9001'

# Custom redis client parameters (i.e.: socket timeout, etc.)
#REDIS_PARAMS  = {}
# Use custom redis client class.
#REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'

# If True, it uses redis' ``SPOP`` operation. You have to use the ``SADD``
# command to add URLs to the redis queue. This could be useful if you
# want to avoid duplicates in your start urls list and the order of
# processing does not matter.
#REDIS_START_URLS_AS_SET = False

# Default start urls key for RedisSpider and RedisCrawlSpider.
#REDIS_START_URLS_KEY = '%(name)s:start_urls'

# Use other encoding than utf-8 for redis.
#REDIS_ENCODING = 'latin1'

设置里面主要包括三个地方,SCHEDULER处理列队的问题(分配任务),DUPEFILTER_CLASS处理去重的问题(任务去重),RedisPipeline处理保存的问题(数据存储)。

代码语言:javascript
复制
# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# Store scraped item in redis for post-processing.
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 300
}

在创建爬虫的时候也有一个调整。

原来非分布式爬虫时的方式如下:

代码语言:javascript
复制
class MySpider(Spider):
    name = 'myspider'

    def parse(self, response):
        # do stuff
        pass

要使用分布式的时候,需要把Spider修改为RedisSpider。

代码语言:javascript
复制
from scrapy_redis.spiders import RedisSpider

class MySpider(RedisSpider):
    name = 'myspider'

    def parse(self, response):
        # do stuff
        pass

抱歉,本章因为时间问题就先写到这里,今天加班太晚啦。读者也早点休息,明天继续。

下一章节,我们通过分析scrapy-redis源码,来进一步了解scrapy-redis框架是如何解决分配任务、任务去重以及把所有爬虫采集的数据汇总一处的三个问题的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.04.12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档