前言

scrapy爬虫框架非常好用,如果再配合scrapy-redis进行分布式爬取,爬取速度将进一步提升!

本文小结了scrapy-redis的使用方法以及如何将现有爬虫通过scrapy-redis更改为分布式爬虫。

使用scrapy-redis

改造前:

import scrapyclass ExampleSpider(scrapy.Spider):name = 'example'allowed_domains = ['example.com']start_urls = ['http://example.com/']def parse(self, response):pass

改造后:

import scrapy
from scrapy import Item, Field
from scrapy_redis.spiders import RedisSpiderclass ExampleSpider(RedisSpider):name = 'example'allowed_domains = ['example.com']start_urls = ['http://example.com/']def parse(self, response):pass

很简单,就是把原来继承的scrapy.Spier,换成了scrapy_redis.RedisSpider

启动爬虫

启动之后,不会立即爬取内容,因为在redis中还没有"任务"

此时,我们向redis中推送一个“任务”

可以看到,紧接着爬虫就去执行了这个任务

我们这里是手动推送一个链接到redis。对于爬虫在执行的过程中,也会抛出itemrequest,抛出的request则会推送至redis

我们重写start_request方法,让这个方法抛出request对象

import scrapy
from scrapy import Item, Field, Request
from scrapy_redis.spiders import RedisSpiderclass ExampleSpider(RedisSpider):name = 'example'allowed_domains = ['example.com']start_urls = ['http://example.com/']def start_requests(self):for i in range(100):yield Request(url="http://google.com/"+str(i))def parse(self, response):pass

然后,重新执行爬虫,当爬虫开始爬取的时候Ctrl + c结束程序

接着,来看下redis

此时,新增两个key,分别是dupefilterrequest,他们是zset类型

根据它们的名字,意思也很明了。

  • dupefilter:用于过滤重复请求,如果请求在这个里面,就不会放入request
  • request:存储待执行的请求任务

查看request

使用pickle反序列化后:

可以看到,是关于这个请求的一些信息,比如,请求头,回调函数等等

在分布式爬虫中,当其他爬虫拿到这个请求时,根据这个请求的信息就知道该如何去执行

items存储

当我们的爬虫抛出item,经由pipeline中间件进行存储。

使用scrapy-redis,我们可以将多个爬虫抛出的item,统一存储至redis数据库中,然后进行统一处理。

在此前提,需要开启scrapy-redis的存储中间件

ITEM_PIPELINES = {'scrapy_redis.pipelines.RedisPipeline': 300
}

我们还可以进行其他的items设置

# The item pipeline serializes and stores the items in this redis key.
# item存储键的设置
REDIS_ITEMS_KEY = '%(spider)s:items'# The items serializer is by default ScrapyJSONEncoder. You can use any
# importable path to a callable object.
# items的序列化器默认是ScrapyJsonEncoder,
# 你也可以使用在任意路径都可导入并调用的对象作为序列化器
# REDIS_ITEMS_SERIALIZER = 'json.dumps'

注意:存储至redis需要序列化,就像存储request那样。默认scrapy-redis使用的是ScrapyJsonEncoder,可以方便的将item序列化。如果你需要使用自定义序列化器,必要条件:序列化对象必须是任意路径下均可调用的对象。

例如:json.dumps,在任意python文件中,通过from json import dumps即可调用,自定义的序列化器也得满足这样。

改写代码如下:

import scrapy
from scrapy import Item, Field, Request
from scrapy_redis.spiders import RedisSpiderclass ExampleSpider(RedisSpider):name = 'example'allowed_domains = ['example.com']start_urls = ['http://example.com/']def start_requests(self):yield Request(url="https://www.baidu.com/",dont_filter=False)def parse(self, response):item = Item()item.fields['hello'] = Field()item['hello'] = 'scrapy-redis'yield item

随便请求一个网址,然后parse方法被调用,设置item并抛出

在redis中查看:

步骤小结

经过上面的探究,要使现有爬虫改成分布式爬虫,步骤非常简单。

1. 安装scrapy_redis

pip install scrapy_redis

2. 配置settings

根据自己的需求,进行配置,我这里对每个配置项进行了简单的翻译

将下面的配置信息,放进settngs.py即可

注意:既然是分布式爬虫,则必须指定你的redis链接哦!,默认是本地

# Enables scheduling storing requests queue in redis.
# 开启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.
# 不清理redis队列,允许暂停/恢复
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).
# 最大闲置时间,防止爬虫在分布式爬取的过程中关闭
# 这个仅在队列是SpiderQueue 或者 SpiderStack才会有作用,
# 也可以阻塞一段时间,当你的爬虫刚开始时(因为刚开始时,队列是空的)
SCHEDULER_IDLE_BEFORE_CLOSE = 10# Store scraped item in redis for post-processing.
# 将已得到的item结果存储至redis中,可用于结果的统一处理
# ITEM_PIPELINES = {#     'scrapy_redis.pipelines.RedisPipeline': 300
# }# The item pipeline serializes and stores the items in this redis key.
# item存储键的设置
REDIS_ITEMS_KEY = '%(spider)s:items'# The items serializer is by default ScrapyJSONEncoder. You can use any
# importable path to a callable object.
# items的序列化器默认是ScrapyJsonEncoder,
# 你也可以使用在任意路径都可导入并调用的对象作为序列化器
# REDIS_ITEMS_SERIALIZER = 'json.dumps'# Specify the host and port to use when connecting to Redis (optional).
# redis配置
# 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客户端参数
#REDIS_PARAMS  = {}
# Use custom redis client class.
# 使用自定义redis客户类
#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.
# 如果为True,它将使用redis的``SPOP``操作,
# 你可以使用``SADD``命令添加urls到队列中。
# 如果你想要让start_url列表中的链接以及当处理顺序不重要时不去重,这是很有用的。
# REDIS_START_URLS_AS_SET = True# If True, it uses redis ``zrevrange`` and ``zremrangebyrank`` operation. You have to use the ``zadd``
# command to add URLS and Scores to redis queue. This could be useful if you
# want to use priority and avoid duplicates in your start urls list.
# 如果为True,它将使用 ``zrevrange``和``zremrangebyrank``操作。
# 你可以用``zadd``命令添加urls和优先级到redis队列中。
# 如果你想让你的start_urls列表中的链接避免去重操作以及设置优先级,这是很有用的。
#REDIS_START_URLS_AS_ZSET = False# Default start urls key for RedisSpider and RedisCrawlSpider.
# 默认start urls的键
# REDIS_START_URLS_KEY = '%(name)s:start_urls'# Use other encoding than utf-8 for redis.
# redis使用utf-8以外的其他编码
#REDIS_ENCODING = 'latin1'

3. 更换爬虫父类

在上诉例子中,爬虫父类是scrapy.Spider,改成scrapy_redis.RedisSpider即可

如果你的父类是CrawlSpider,同样的操作改为scrapy_redis.RedisCrawlSpider

如果你是自定义父类,则需要额外继承scrapy_redis.RedisMixin,并实现

@classmethod
def from_crawler(self, crawler, *args, **kwargs):obj = super(自定义的类名, self).from_crawler(crawler, *args, **kwargs)obj.setup_redis(crawler)return obj

4. Items Pipeline

这一步骤非强制性要求

如果你希望爬虫爬下来就保存至数据库,比如我现在的爬虫是保存至mongo数据库的,每个爬虫都与mongo建立链接,爬下来就存进去。

如果你希望数据后期统一处理,则可以增加'scrapy_redis.pipelines.RedisPipeline': 300

ITEM_PIPELINES = {...'scrapy_redis.pipelines.RedisPipeline': 300
}

参考文章

[1] redis常用命令

[2] scrapy-redis详解

Scrapy-Redis使用教程将现有爬虫修改为分布式爬虫相关推荐

  1. python爬虫:scrapy-redis分布式爬虫(详细版)

    本文是将现有的scrapy爬虫改造为分布式爬虫,为详细版,简略版请看https://blog.csdn.net/Aacheng123/article/details/114265960 使用scrap ...

  2. python3爬虫(9)分布式爬虫与对等分布式爬虫

    原文链接:http://www.dataguru.cn/thread-529666-1-1.html 谈谈主从分布式爬虫与对等分布式爬虫的优劣 主从式(Master-Slave) 对于主从式而言,有一 ...

  3. 【Python3爬虫】学习分布式爬虫第一步--Redis分布式爬虫初体验

    一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...

  4. 爬虫总结(四)-- 分布式爬虫

    分布式爬虫的演习. 分布式爬虫问题其实也就是多台机器多个 spider 对 多个 url 的同时处理问题,怎样 schedule 这些 url,怎样汇总 spider 抓取的数据.最简单粗暴的方法就是 ...

  5. 分布式爬虫原理之分布式爬虫原理

    我们在前面已经实现了Scrapy微博爬虫,虽然爬虫是异步加多线程的,但是我们只能在一台主机上运行,所以爬取效率还是有限的,分布式爬虫则是将多台主机组合起来,共同完成一个爬取任务,这将大大提高爬取的效率 ...

  6. python 协程可以嵌套协程吗_Python实战异步爬虫(协程)+分布式爬虫(多进程)

    引言:我们在写爬虫时常会遇到这样的问题,当需要爬取多个URL时,写一个普通的基于requests库的爬虫程序爬取时间会很长.因为是顺序请求网页的,而网页请求和获得响应过程比较耗费时间,程序不得不等待获 ...

  7. python异步爬虫_Python实战异步爬虫(协程)+分布式爬虫(多进程)

    转自:https://blog.csdn.net/SL_World/article/details/86633611 在讲解之前,我们先来通过一幅图看清多进程和协程的爬虫之间的原理及其区别.(图片来源 ...

  8. Scrapy-Redis分布式爬虫框架详解-邮乐网(ule.com)

    python编程快速上手(持续更新中-) python爬虫从入门到精通 Scrapy爬虫框架 文章目录 python编程快速上手(持续更新中-) python爬虫从入门到精通 Scrapy爬虫框架 一 ...

  9. Python进阶之Scrapy-redis分布式爬虫抓取当当图书

    Python进阶之Scrapy-redis分布式爬虫抓取当当图书 1. 准备工作 1.1 安装scrapy-redis 1.2 在windows安装redis程序 1.3 打开redis服务 2. 需 ...

最新文章

  1. go语言中的int类型
  2. 物联网设计四大独特挑战的解决方案
  3. 【Java并发编程】—–“J.U.C”:ConcurrentLinkedQueue
  4. Dataset之Knifey-Spoony:Knifey-Spoony数据集的简介、下载、使用方法之详细攻略
  5. 软件工程——团队作业3
  6. isight参数优化理论与实例详解_详解oracle数据库优化参数--cursor_sharing
  7. 欢迎加入Hello China技术讨论群组-QQ群:38467832
  8. 微服务应用容器化场景中常见问题总结
  9. [转]WebService 之 WSDL文件 讲解
  10. 基于JAVA+SpringMVC+Mybatis+MYSQL的体育器材管理系统
  11. 当你负债累累,看不到方向,众叛亲离时,该如何面对?
  12. Android中实现非本地图片的点击态
  13. 一键批量检测微信是否被好友删除
  14. nu.xom:Element
  15. js版本飞机大战(完整代码)
  16. 【数学】弧度和角度的转换
  17. Linux电脑睡眠后黑屏打不开,电脑睡眠后黑屏打不开 电脑睡眠后黑屏打不开的原因...
  18. 【题解】[POI2006」Tet-Tetris 3D
  19. Web必备性能压力测试工具WebBench与ApcheBench(ab)详解
  20. Explaining and Harnessing Adversarial Examples——论文的学习笔记01

热门文章

  1. 东财《金融法X》综合作业
  2. 阿里云服务器 云对象存储OOS(一) ---入门级操作
  3. 手把手教你如何PCB板材选型(一)
  4. 小程序如何推广?这里有5招
  5. 自动化构建java应用实战
  6. PTA L1-049 天梯赛座位分配(20分)(python)
  7. meo学习笔记3:并行与并发,线程与进程的区别
  8. 【R言R语】算法工程师入职一年半的总结与感悟
  9. 达梦数据库DM8的DM管理工具manger命令行启动时出错Manager:10369的处理方法
  10. 【游戏王arc-v卡片力量SP改名字ID教程】