重写scrapy中间件之RetryMiddleware
来源:互联网 发布:专业网络公关 编辑:程序博客网 时间:2024/06/06 07:01
重写scrapy中间件RetryMiddleware
在爬取得过程中难免会遇到各种错误,如timeout或者404。而且在用ip代理池时,不是所有的代理都是稳定的,所以对于失败的代理我们需要做一些处理,例如删除操作。而由于不稳定代理引起的请求我们需要重新发起。这时候就有必要重写RetryMiddleware,来实现一些自己想要的操作。
- 理解RetryMiddleware源码
- 重写RetryMiddleware
RetryMiddleware部分源码
class RetryMiddleware(object): # 当遇到以下Exception时进行重试 EXCEPTIONS_TO_RETRY = (defer.TimeoutError, TimeoutError, DNSLookupError, ConnectionRefusedError, ConnectionDone, ConnectError, ConnectionLost, TCPTimedOutError, ResponseFailed, IOError, TunnelError) def __init__(self, settings): ''' 这里涉及到了settings.py文件中的几个量 RETRY_ENABLED: 用于开启中间件,默认为TRUE RETRY_TIMES: 重试次数, 默认为2 RETRY_HTTP_CODES: 遇到哪些返回状态码需要重试, 一个列表,默认为[500, 503, 504, 400, 408] RETRY_PRIORITY_ADJUST:调整相对于原始请求的重试请求优先级,默认为-1 ''' if not settings.getbool('RETRY_ENABLED'): raise NotConfigured self.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') def process_response(self, request, response, spider): # 在之前构造的request中可以加入meta信息dont_retry来决定是否重试 if request.meta.get('dont_retry', False): return response # 检查状态码是否在列表中,在的话就调用_retry方法进行重试 if response.status in self.retry_http_codes: reason = response_status_message(response.status) # 在此处进行自己的操作,如删除不可用代理,打日志等 return self._retry(request, reason, spider) or response return response def process_exception(self, request, exception, spider): # 如果发生了Exception列表中的错误,进行重试 if isinstance(exception, self.EXCEPTIONS_TO_RETRY) \ and not request.meta.get('dont_retry', False): # 在此处进行自己的操作,如删除不可用代理,打日志等 return self._retry(request, exception, spider)
自己想要的操作在上面已经标出来了,只要在其中加入自己的代码就可以满足大部分要求。具体如下:
class MyRetryMiddleware(RetryMiddleware): logger = logging.getLogger(__name__) def delete_proxy(self, proxy): if proxy: # delete proxy from proxies pool def process_response(self, request, response, spider): if request.meta.get('dont_retry', False): return response if response.status in self.retry_http_codes: reason = response_status_message(response.status) # 删除该代理 self.delete_proxy(request.meta.get('proxy', False)) time.sleep(random.randint(3, 5)) self.logger.warning('返回值异常, 进行重试...') return self._retry(request, reason, spider) or response return response def process_exception(self, request, exception, spider): if isinstance(exception, self.EXCEPTIONS_TO_RETRY) \ and not request.meta.get('dont_retry', False): # 删除该代理 self.delete_proxy(request.meta.get('proxy', False)) time.sleep(random.randint(3, 5)) self.logger.warning('连接异常, 进行重试...') return self._retry(request, exception, spider)
其中_retry方法有如下作用:
1、对request.meta中的retry_time进行+1
2、将retry_times和max_retry_time进行比较,如果前者小于等于后者,利用copy方法在原来的request上复制一个新request,并更新其retry_times,并将dont_filter设为True来防止因url重复而被过滤。
阅读全文
0 0
- 重写scrapy中间件之RetryMiddleware
- scrapy自定义RetryMiddleware
- zg手册 之 scrapy 开发(3)-- 下载中间件
- scrapy中的下载器中间件
- Scrapy爬虫(八):中间件的使用实例
- Scrapy 通过中间件实现随机User-Agent
- Scrapy——流程以及middleware中间件
- scrapy如何从外部路径引入中间件
- NodeJS Connect URL重写中间件组件
- Connect中间件——重写URL
- scrapy源码分析(十二)---------下载中间件RobotsTxtMiddleware
- 八.Scrapy 学习下Spider中间件Spider Middlewares
- 中间件之RMI
- Nodejs express之中间件
- RPC中间件之Hessian
- 消息中间件之RabbitMQ
- 中间件之权限控制
- 分布式之消息中间件
- C、C++一次将整个文件读入内存
- uva12108
- 数据结构之--优先级队列(Java代码)
- 浅谈KVC
- 51nod 1627 区间交
- 重写scrapy中间件之RetryMiddleware
- Java 内置数据类型总结
- HDOJ-1702 ACboy needs your help again!
- es6学习过程(二)
- 标准模板库 STL-1 编程题#1(Coursera 程序设计与算法 专项课程3;用法:迭代器 ostream_iterator,容器 set)
- CanFestival win32程序调试过程记录 版本CanFestival-3-8bfe0ac00cdb
- CodeForces
- 模板中使用str_limit限定字符长度
- C/C++训练1---最大公约数与最小公倍数