当前位置: 首页 > news >正文

高级深入--day44

Scrapy 和 scrapy-redis的区别

Scrapy 是一个通用的爬虫框架,但是不支持分布式,Scrapy-redis是为了更方便地实现Scrapy分布式爬取,而提供了一些以redis为基础的组件(仅有组件)。

pip install scrapy-redis

Scrapy-redis提供了下面四种组件(components):(四种组件意味着这四个模块都要做相应的修改)

  • Scheduler
  • Duplication Filter
  • Item Pipeline
  • Base Spider

scrapy-redis架构

如上图所⽰示,scrapy-redis在scrapy的架构上增加了redis,基于redis的特性拓展了如下组件:

Scheduler

Scrapy改造了python本来的collection.deque(双向队列)形成了自己的Scrapy queue(https://github.com/scrapy/queuelib/blob/master/queuelib/queue.py)),但是Scrapy多个spider不能共享待爬取队列Scrapy queue, 即Scrapy本身不支持爬虫分布式,scrapy-redis 的解决是把这个Scrapy queue换成redis数据库(也是指redis队列),从同一个redis-server存放要爬取的request,便能让多个spider去同一个数据库里读取。

Scrapy中跟“待爬队列”直接相关的就是调度器Scheduler,它负责对新的request进行入列操作(加入Scrapy queue),取出下一个要爬取的request(从Scrapy queue中取出)等操作。它把待爬队列按照优先级建立了一个字典结构,比如:

    {优先级0 : 队列0优先级1 : 队列1优先级2 : 队列2}

然后根据request中的优先级,来决定该入哪个队列,出列时则按优先级较小的优先出列。为了管理这个比较高级的队列字典,Scheduler需要提供一系列的方法。但是原来的Scheduler已经无法使用,所以使用Scrapy-redis的scheduler组件。

Duplication Filter

Scrapy中用集合实现这个request去重功能,Scrapy中把已经发送的request指纹放入到一个集合中,把下一个request的指纹拿到集合中比对,如果该指纹存在于集合中,说明这个request发送过了,如果没有则继续操作。这个核心的判重功能是这样实现的:

    def request_seen(self, request):# 把请求转化为指纹  fp = self.request_fingerprint(request)# 这就是判重的核心操作  ,self.fingerprints就是指纹集合if fp in self.fingerprints:return True  #直接返回self.fingerprints.add(fp) #如果不在,就添加进去指纹集合if self.file:self.file.write(fp + os.linesep)

在scrapy-redis中去重是由Duplication Filter组件来实现的,它通过redis的set 不重复的特性,巧妙的实现了Duplication Filter去重。scrapy-redis调度器从引擎接受request,将request的指纹存⼊redis的set检查是否重复,并将不重复的request push写⼊redis的 request queue。

引擎请求request(Spider发出的)时,调度器从redis的request queue队列⾥里根据优先级pop 出⼀个request 返回给引擎,引擎将此request发给spider处理。

Item Pipeline

引擎将(Spider返回的)爬取到的Item给Item Pipeline,scrapy-redis 的Item Pipeline将爬取到的 Item 存⼊redis的 items queue。

修改过Item Pipeline可以很方便的根据 key 从 items queue 提取item,从⽽实现 items processes集群。

Base Spider

不在使用scrapy原有的Spider类,重写的RedisSpider继承了Spider和RedisMixin这两个类,RedisMixin是用来从redis读取url的类。

当我们生成一个Spider继承RedisSpider时,调用setup_redis函数,这个函数会去连接redis数据库,然后会设置signals(信号):

  • 一个是当spider空闲时候的signal,会调用spider_idle函数,这个函数调用schedule_next_request函数,保证spider是一直活着的状态,并且抛出DontCloseSpider异常。

  • 一个是当抓到一个item时的signal,会调用item_scraped函数,这个函数会调用schedule_next_request函数,获取下一个request。

相关文章:

  • AI for Security:智能化安全对抗的困境
  • 华为OD 最大岛屿体积(100分)【java】A卷+B卷
  • Postgresqlddl在事务中可以回滚,truncate时relfilenode在当前会话会改变
  • 《嵌入式软\硬件开发难点-2023-10-29》
  • 基于Qt 文本读写(QFile/QTextStream/QDataStream)实现
  • LeetCode题:88合并两个有序数组,283移动零,448找到所有数组中消失的数字
  • volatile 系列之如何解决可见性问题
  • 【C++代码】爬楼梯,不同路径,整数拆分,不同搜索树,动态规划--代码随想录
  • QT C++ AES字符串加密实现
  • 设计模式中继承和组合的总结
  • MyString字符串类
  • TOGAF(企业架构)
  • VSCode snippets
  • Android11系统桌面隐藏指定APP图标
  • nginx请求时找路径问题
  • 【面试系列】之二:关于js原型
  • conda常用的命令
  • js
  • spring security oauth2 password授权模式
  • Vue实战(四)登录/注册页的实现
  • Windows Containers 大冒险: 容器网络
  • 大快搜索数据爬虫技术实例安装教学篇
  • 基于遗传算法的优化问题求解
  • 老板让我十分钟上手nx-admin
  • 聊一聊前端的监控
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 我的面试准备过程--容器(更新中)
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 正则与JS中的正则
  • 追踪解析 FutureTask 源码
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #HarmonyOS:基础语法
  • (09)Hive——CTE 公共表达式
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (简单) HDU 2612 Find a way,BFS。
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (转)创业的注意事项
  • **python多态
  • *2 echo、printf、mkdir命令的应用
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .Net 8.0 新的变化
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • []Telit UC864E 拨号上网
  • [BZOJ 1040] 骑士
  • [BZOJ 2142]礼物(扩展Lucas定理)
  • [GYCTF2020]Ez_Express
  • [HackMyVM]靶场Crossbow
  • [JavaScript]_[初级]_[不使用JQuery原生Ajax提交表单文件并监听进度]
  • [Java性能剖析]Sun JDK基本性能剖析工具介绍
  • [LeeCode]-Divide Two Integers 不用乘除的除法运算