爬虫工作量由小到大的思维转变---<第三十九章 Scrapy-redis 常用的那个RetryMiddleware>

本文主要是介绍爬虫工作量由小到大的思维转变---<第三十九章 Scrapy-redis 常用的那个RetryMiddleware>,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

为什么要讲这个RetryMiddleware呢?因为他很重要~ 至少在你装配代理ip或者一切关于重试的时候需要用到!----最关键的是:大部分的教学视频里面,没有提及这个!!!!

正文:

源代码分析

这个RetryMiddleware是来自:

from scrapy.downloadermiddlewares.retry import RetryMiddleware

我们可以看他的源码:(我已经添加了中文注释)

class RetryMiddleware:EXCEPTIONS_TO_RETRY = (defer.TimeoutError,  # 等待超时错误TimeoutError,  # 执行超时错误DNSLookupError,  # DNS解析错误ConnectionRefusedError,  # 连接被拒绝错误ConnectionDone,  # 连接已关闭错误ConnectError,  # 连接错误ConnectionLost,  # 连接丢失错误TCPTimedOutError,  # TCP超时错误ResponseFailed,  # 响应失败错误IOError,  # IO错误(通常发生在HttpCompression中间件尝试解压缩空响应时)TunnelError,  # 隧道错误)def __init__(self, settings):if not settings.getbool("RETRY_ENABLED"):raise NotConfiguredself.max_retry_times = settings.getint("RETRY_TIMES")self.retry_http_codes = set(int(x) for x in settings.getlist("RETRY_HTTP_CODES"))self.priority_adjust = settings.getint("RETRY_PRIORITY_ADJUST")@classmethoddef from_crawler(cls, crawler):return cls(crawler.settings)def process_response(self, request, response, spider):if request.meta.get("dont_retry", False):return responseif response.status in self.retry_http_codes:reason = response_status_message(response.status)return self._retry(request, reason, spider) or responsereturn responsedef process_exception(self, request, exception, spider):if isinstance(exception, self.EXCEPTIONS_TO_RETRY) and not request.meta.get("dont_retry", False):return self._retry(request, exception, spider)def _retry(self, request, reason, spider):max_retry_times = request.meta.get("max_retry_times", self.max_retry_times)priority_adjust = request.meta.get("priority_adjust", self.priority_adjust)return get_retry_request(request,reason=reason,spider=spider,max_retry_times=max_retry_times,priority_adjust=priority_adjust,)

这段代码是Scrapy框架中scrapy.downloadermiddlewares.retry模块中的RetryMiddleware类。它是重试下载器中间件,用于处理下载请求的重试逻辑。

让我来逐行解释这段代码的注释和功能:

  1. EXCEPTIONS_TO_RETRY是一个元组,包含了需要重试的异常类型。如果发生这些异常而且请求没有设置dont_retry元数据标志,则会进行重试。
  2. __init__方法初始化重试中间件的参数。它从settings中获取配置信息,包括是否启用重试、最大重试次数、重试的HTTP响应状态码和优先级调整。
  3. from_crawler是一个类方法,用于从crawler对象获取设置,创建RetryMiddleware实例并返回。
  4. process_response方法处理响应。如果请求的dont_retry元数据标志为True,直接返回响应。如果响应的状态码在重试的HTTP响应状态码列表中,使用_retry方法进行重试并返回重试请求,否则返回响应本身。
  5. process_exception方法处理异常。如果发生的异常属于EXCEPTIONS_TO_RETRY类型并且请求的dont_retry元数据标志为False,使用_retry方法进行重试。
  6. _retry方法执行实际的重试逻辑。它从请求的元数据中获取最大重试次数和优先级调整,然后使用get_retry_request方法创建一个带有重试参数的新请求,并返回该请求。

修改源代码:

为什么要修改这个源代码?因为,在修改他的时候,你能通过这个已经封装好的重试中间件,做很多自定义的事情!!!

修改后的代码:(这里以:对超过重试次数的ip在redis里面删除为例)

from scrapy.downloadermiddlewares.retry import RetryMiddleware# 确保在 retry_times 用尽后仍然移除失败代理,需要重写 RetryMiddleware
class RedisRetryMiddleware(RetryMiddleware):"""继承并重写RetryMiddleware,添加代理移除逻辑"""def __init__(self, settings):# Redis 实例化逻辑,读取配置self.server = redis.StrictRedis(host=settings.get('REDIS_HOST'),port=settings.get('REDIS_PORT'),db=settings.get('REDIS_DB'))  #获取redis的链接设置self.proxy_key = settings.get('REDIS_PROXY_KEY') #redis的key值super(RedisRetryMiddleware, self).__init__(settings)@classmethoddef from_crawler(cls, crawler):# 读取爬虫配置的 RETRY_TIMESreturn cls(crawler.settings)def _retry(self, request, reason, spider):proxy = request.meta.get('proxy')if proxy:# 代理失败,删除代理self.server.srem(self.proxy_key, proxy)spider.logger.debug(f'Remove Proxy: {proxy}. Reason: {reason}')# 调用超类(爬虫默认)重试方法return super(RedisRetryMiddleware, self)._retry(request, reason, spider)

总结:

from scrapy.downloadermiddlewares.retry import RetryMiddleware是用来导入Scrapy框架内置的RetryMiddleware中间件类。这个中间件类用于处理请求的重试逻辑,当请求失败或遇到特定的异常时,可以根据配置的参数进行自动重试。

在Scrapy-Redis中,你可以根据需要使用RetryMiddleware来实现诸如以下功能:

  1. 增加请求重试次数: 通过修改RETRY_TIMES设置项来增加请求的最大重试次数。
  2. 处理HTTP响应错误: 可以配置RETRY_HTTP_CODES设置项,指定需要重试的HTTP响应状态码。当相应的HTTP响应状态码出现时,中间件会自动发起重试。
  3. 自定义重试机制: 可以通过重写process_responseprocess_exception方法,在特定条件下进行自定义的重试逻辑判断。例如,可以根据响应内容确定是否需要重试,或是自定义异常类型进行处理。
  4. 调整请求优先级: 可以通过RETRY_PRIORITY_ADJUST设置项来调整重试请求的优先级,使其具有比原始请求更高或更低的优先级。
  5. 在分布式爬虫中使用: 在Scrapy-Redis中,可以结合Redis数据库和分布式队列使用RetryMiddleware,实现在集群中共享重试请求和状态。

总而言之,RetryMiddleware是Scrapy框架提供的一个非常实用的中间件,用于处理请求的重试,可以根据需要进行配置和定制。在Scrapy-Redis中,它常常被用来增加爬虫的容错性和稳定性,确保爬取的数据的完整性和准确性

这篇关于爬虫工作量由小到大的思维转变---<第三十九章 Scrapy-redis 常用的那个RetryMiddleware>的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/646336

相关文章

Redis 中的热点键和数据倾斜示例详解

《Redis中的热点键和数据倾斜示例详解》热点键是指在Redis中被频繁访问的特定键,这些键由于其高访问频率,可能导致Redis服务器的性能问题,尤其是在高并发场景下,本文给大家介绍Redis中的热... 目录Redis 中的热点键和数据倾斜热点键(Hot Key)定义特点应对策略示例数据倾斜(Data S

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

Java常用注解扩展对比举例详解

《Java常用注解扩展对比举例详解》:本文主要介绍Java常用注解扩展对比的相关资料,提供了丰富的代码示例,并总结了最佳实践建议,帮助开发者更好地理解和应用这些注解,需要的朋友可以参考下... 目录一、@Controller 与 @RestController 对比二、使用 @Data 与 不使用 @Dat

Mysql中深分页的五种常用方法整理

《Mysql中深分页的五种常用方法整理》在数据量非常大的情况下,深分页查询则变得很常见,这篇文章为大家整理了5个常用的方法,文中的示例代码讲解详细,大家可以根据自己的需求进行选择... 目录方案一:延迟关联 (Deferred Join)方案二:有序唯一键分页 (Cursor-based Paginatio

redis+lua实现分布式限流的示例

《redis+lua实现分布式限流的示例》本文主要介绍了redis+lua实现分布式限流的示例,可以实现复杂的限流逻辑,如滑动窗口限流,并且避免了多步操作导致的并发问题,具有一定的参考价值,感兴趣的可... 目录为什么使用Redis+Lua实现分布式限流使用ZSET也可以实现限流,为什么选择lua的方式实现

Redis中管道操作pipeline的实现

《Redis中管道操作pipeline的实现》RedisPipeline是一种优化客户端与服务器通信的技术,通过批量发送和接收命令减少网络往返次数,提高命令执行效率,本文就来介绍一下Redis中管道操... 目录什么是pipeline场景一:我要向Redis新增大批量的数据分批处理事务( MULTI/EXE

Python实现常用文本内容提取

《Python实现常用文本内容提取》在日常工作和学习中,我们经常需要从PDF、Word文档中提取文本,本文将介绍如何使用Python编写一个文本内容提取工具,有需要的小伙伴可以参考下... 目录一、引言二、文本内容提取的原理三、文本内容提取的设计四、文本内容提取的实现五、完整代码示例一、引言在日常工作和学

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

Redis中的常用的五种数据类型详解

《Redis中的常用的五种数据类型详解》:本文主要介绍Redis中的常用的五种数据类型详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis常用的五种数据类型一、字符串(String)简介常用命令应用场景二、哈希(Hash)简介常用命令应用场景三、列表(L

Redis解决缓存击穿问题的两种方法

《Redis解决缓存击穿问题的两种方法》缓存击穿问题也叫热点Key问题,就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击,本文给大家介绍了Re... 目录引言解决办法互斥锁(强一致,性能差)逻辑过期(高可用,性能优)设计逻辑过期时间引言缓存击穿:给