scrapy是一个python爬虫框架,爬取的效率极高,具有高度的定制性,但是不支持分布式。而scrapy-redis是一套基于redis库,运行在scrapy框架之上的组件,可以让scapy支持分布式策略

Slaver端共享Master端redis数据库里的item 队列、请求队列和请求指纹集合。

选择redis数据库的原因:

  redis支持主从同步,而且数据都是缓存在内存中的,所以基于redis的分布式爬虫,对请求和数据的高频率读取效率都非常高

    scrapy-redis和scrapy的关系就像电脑和固态硬盘一样,是电脑中的一个插件,能让电脑更快的运行

    scrapy是一个爬虫框架,scrapy-redis则是这个框架上可以选择的插件,它可以让爬虫跑得更

解释说明:

  1. 从优先级队列中获取requests对象,交给engine
  2. engine将requests对此昂交给下载器下载,期间会通过downlomiddleware的process_request方法
  3. 下载器完成下载,获得response对象,将该对象交给engine,期间会经过downloadmiddleware的process_response()方法
  4. engine将获得的response对象交给spider进行解析,期间会经过spidermiddleware的process_spider_input()方法
  5. spider解析下载器下载下来的response,返回item或links(url)
  6. item或者link经过spidermiddleware的process_spider_out()方法,交给engine
  7. engine将item交给item pipeline,将links交给调度器
  8. 在调度器中,先将requests对象利用scrapy内置的指纹函数生成一个指纹
  9. 如果requests对象中的don't filter参数设置为False,并且该requests对象的指纹不在信息指纹的队列中,那么就把该requests对象放到优先级队列中

中间件:

  spider与engine之间(爬虫中间件)

    介于scrapy引擎和爬虫之间的框架,主要工作就是处理爬虫的响应输入和请求的输出

  download与engine之间(下载器中间件)

    介于scrapy引擎和下载器之间的框架,主要是处理scrapy引擎与下载器之间的请求和响应

scrapy框架中的middleware.py

  1. Scrapy Middleware有以下几个函数被管理
    1. process_spider_input:接收一个response对象并处理
    2. process_spider_exception:spider出现异常时被调用
    3. process_spider_output:当spider处理response返回result时,就会调用该方法
    4. process_spider_requests:当spider发出请求时,被调用
  2. Download Middleware有以下几个函数被管理
    1. process_requests:requests通过下载中间件的时候,该方法被调用,这里可以通过设置代理,设置request.meta['proxy']就OK了
    2. process_response:下载结果经过中间件的时候会被这个方法解惑来进行处理
    3. process_exception:下载过程中出现异常的时候会被调用

Scrapy的优缺点:

  1. 优点
    1. scrapy是异步处理的,写middleware,方便写一些统一的过滤器
  2. 缺点
    1. 基于python的爬虫框架,扩展性比较差,基于twisted框架,运行中的exception是不会干掉reactor,并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉

Scrapy-Redis提供了四种组件(四种组件也就意味着这四个模块都需要做出相应的改动):

  1. Scheduler
    1. scrapy改变了python原本的collection.deque(双向队列)形成了自己的Scrapy queue,但是Scrapy多个spider不能共享爬取队列Scrapy queue,也就是Scrapy本身不支持爬虫的分布式,scrapy-redis的解决是把这个Scrapy queue换成了redis数据库(也是指redis队列),从同一个redis-server存放要爬取的request,就可以让多个爬虫去同一个数据库里读取了
    2. scrapy中跟待爬队列直接相关的就是调度器Scheduler,它负责对新的request进行入列操作(加入到Scrapy queue),取出下一个要爬的request(从Scrapy queue中取出来)等操作。它把待爬队列按照优先级建立一个字典结构,然后根据request中的优先级,再来决定该入哪个队列,出列时就按照优先级较小的优先出列,为了管理这个比较高级的队列字典,Scheduler需要提供一系列的方法,但是原来的Scheduler已经无法使用,所以使用Scrapy-redis的Scheduler组件
  2. Duplication Filter
    1. scrapy中用集合实现这个request的去重功能,scrapy中把已经发送的request指纹放入到一个集合中,把下一个request的指纹拿到集合中进行比较,如果该指纹已经存在集合中了,说了这个request发送过了,如果没有的话就继续这个操作
    2. 在scrapy-redis中去重是由Duplication Filter组件来实现的,它通过redis的set不重复的特性,巧妙的实现了Duplicating Filter去重。scrapy-redis调度器从引擎接受request,将request的指纹存入redis的set检查是否产生了重复,并将不重复的request push写入redis的request queue
    3. 引擎请求request时,调度器从redis的request queue队列里根据优先级进行pop出一个request返回给engine,engine将这个request发送给spider进行处理
  3. Item Pipeline
    1. 引擎(spider返回的)将爬取到的item给item pipeline,scrapy-redis的item pipeline将爬取到的item存入到redis的items queue
    2. 修改过的item pipeline可以很方便的根据key从items queue提取item,从而实现items processes集群
  4. Base Spider
    1. 不在使用scrapy原有的Spider类,重写RedisSpider继承了Spider和RedisMixin这两个类,RedisMixin是用来从redis中读取url的类
    2. 当我们生成一个Spider继承RedisSpider的时候,调用setup_redis函数,这个函数会去连接redis数据库,然后就设置signals(信号):一个是当spider空闲时候的signal,会调用spider_idle函数,这个函数调用scheduler_next_request函数,保证spider是一直活着的状态,并且抛出DontCloseSpider异常,还有一个就是当抓到一个item的signal,会调用item_scrapy函数,这个函数会调用scheduler_next_request函数,获取下一个request。

Scrapy-Redis分布式策略:

    首先要说一下Master端和Slaver端

    1. Master
      1. 核心服务器,搭建Redis数据库,不负责爬取,只负责url指纹判断是否重复、request的分配、以及数据的存储
    2. Slaver
      1. 爬虫程序执行端,负责执行爬虫程序,运行过程中提交新的request给Master

    

    首先Slaver端从Master端拿任务(request, url)进行数据爬取,Slaver抓取数据的同时,产生新的request就提交给Master进行处理

    Master端只有一个Redis数据库,负责将未处理的request去重和任务分配,将处理后的request加入待爬取的队列,并且存储爬取的数据

将scrapy变成scrapy-redis的过程(前提是已经安装好了scrapy-redis)

  1. 修改settings.py配置文件,最简单的方式就是使用redis来替换当前电脑的内存,并且同时配置好redis数据库相关的内容

    # 这个是需要手动加上的,通过scrapy-redis自带的pipeline将item存入redis中
    ITEM_PIPELINES = {'scrapy_redis.pipelines.RedisPipeline': 400
    }
    # 启动redis自带的去重
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    # 启用调度器
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    # 是否在关闭spider的时候保存记录
    SCHEDULER_PERSIST = True
    # 使用优先级调度请求队列(默认使用)
    SCHEDULER_QUEUE_CLASS =
    'scrapy_redis.queue.SpiderPriorityQueue'
    # 指定redis的地址和端口,有密码的需要加上密码
    REDIS_HOST = '127.0.0.1'
    REDIS_PORT = ''
    # 如果你的redis设了密码就需要加上密码,
    REDIS_PARAMS = {
    'password': '',
    }

scrapy和scrapy-redis的区别的更多相关文章

  1. <scrapy爬虫>scrapy命令行操作

    1.mysql数据库 2.mongoDB数据库 3.redis数据库 1.创建项目 scrapy startproject myproject cd myproject 2.创建爬虫 scrapy g ...

  2. python爬虫scrapy之scrapy终端(Scrapy shell)

    Scrapy终端是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码. 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码. ...

  3. 第三百三十一节,web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令

    第三百三十一节,web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令 Scrapy框架安装 1.首先,终端执行命令升级pip: python -m pip install --u ...

  4. Scrapy之Scrapy shell

    Scrapy Shell Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据 ...

  5. 十 web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令

    Scrapy框架安装 1.首先,终端执行命令升级pip: python -m pip install --upgrade pip2.安装,wheel(建议网络安装) pip install wheel ...

  6. Django缓存系统选择之Memcached与Redis的区别与性能对比

    Django支持使用Memcached和Redis这两种流行的内存型数据库作为缓存系统.我们今天来看Memcached和Redis的区别和性能对比. redis和memcached的区别 1.Redi ...

  7. scrapy - 给scrapy 的spider 传值

    scrapy - 给scrapy 的spider 传值 方法一: 在命令行用crawl控制spider爬取的时候,加上-a选项,例如: scrapy crawl myspider -a categor ...

  8. MySql、Mongodb和Redis的区别

    NoSQL 的全称是 Not Only SQL,也可以理解非关系型的数据库,是一种新型的革命式的数据库设计方式,不过它不是为了取代传统的关系型数据库而被设计的,它们分别代表了不同的数据库设计思路. M ...

  9. python - scrapy 爬虫框架 ( redis去重 )

    1.  使用内置,并加以修改 ( 自定义 redis 存储的 keys ) settings 配置 # ############### scrapy redis连接 ################# ...

  10. Scrapy中scrapy.Request和response.follow的区别

    在写scrapy的spider类的parse方法的时候,有些链接需要提取出来继续爬取,这里scrapy提供了一些方法可以方便的实现这个功能,总结如下: 假设我们的目标a标签是target_a 方法1: ...

随机推荐

  1. Android进阶之绘制-自定义View完全掌握(四)

    前面的案例中我们都是使用系统的一些控件通过组合的方式来生成我们自定义的控件,自定义控件的实现还可以通过自定义类继承View来完成.从该篇博客开始,我们通过自定义类继承View来实现一些我们自定义的控件 ...

  2. Oracle面对“数据倾斜列使用绑定变量”场景的解决方案

    1.背景知识介绍 2.构造测试用例 3.场景测试 4.总结 1.背景知识介绍     我们知道,Oracle在传统的OLTP(在线事务处理)类系统中,强烈推荐使用绑定变量,这样可以有效的减少硬解析从而 ...

  3. JAVA 获取时间段内的每一天

    public class day { public static void main(String[] args) { // TODO Auto-generated method stub Strin ...

  4. d3.js制作蜂巢图表带动画效果

    以上是效果图,本图表使用d3.js v4制作.图表主要功能是在六边形格子中显示数据,点击底部图标可以切换指定格子高亮显示,图表可以随浏览器任意缩放. 1.图表的主体结构是由正六边形组成,使用d3生成六 ...

  5. C# - AutoMapper之不同类型的转换

    一.Dto & Model约定 class TestDto { public string Name { get; set; } public int Age { get; set; } pu ...

  6. MSIL实用指南-生成while语句

    本篇讲解怎样生成while语句.while语句是编程语言中很重要的循环语句,它的结构是while(<表达式>) <语句或语句块> 当表达式的结果为true时就一直执行语句或语句 ...

  7. 【Linux命令】nohup命令

    nohup命令 不挂断的运行,它会使您的脚本被忽略SIGHUP,并重定向stdout/stderr到一个文件nohup.out,以便在您注销后该命令可以在后台继续运行. 1)语法 nohup Comm ...

  8. C#开发BIMFACE系列18 服务端API之获取模型数据3:获取构件属性

    系列目录     [已更新最新开发文章,点击查看详细] 本篇主要介绍如何获取单文件/模型下单个构建的属性信息. 请求地址:GET https://api.bimface.com/data/v2/fil ...

  9. CodeForces 311 B Cats Transport 斜率优化DP

    题目传送门 题意:现在有n座山峰,现在 i-1 与 i 座山峰有 di长的路,现在有m个宠物, 分别在hi座山峰,第ti秒之后可以被带走,现在有p个人,每个人会从1号山峰走到n号山峰,速度1m/s.现 ...

  10. Mysql相关:navicat for mysql 加注释

    在 navicat 中有三种注释的书写方式: 以 # 开头的字符串,可以多个 # 连续以 – 开头的字符串,注意:只能是 – ,而且 – 后面需要加一个半角空格以 /* */ 包围的字符串,类似于 J ...