def process_response(self, request, response, spider): """ 要考虑两种情况,一是被封,二是ip 失效 :param request: :param response: :param spider: :return: """ proxy_str = request.meta['proxy'] proxy = ProxyItem.parse(proxy_str) # 持有的是方法,只有一个实例,所以并发时 self.proxy 应该是不准确的,需从 request 获取 if isinstance(response, ErrorResponse): proxy_manager.fail(proxy) return self.on_request_error(request, response, spider) code, _ = douyin.parse_result(response.body.decode()) if code == 1: proxy_manager.success(proxy) elif code == 2: proxy_manager.banned(proxy) if douyin_spider.ANONYMOUS: # 匿名则忽略并继续 ,不匿名返回处理 return self.on_request_error(request, response, spider) else: return response else: proxy_manager.fail(proxy) return self.on_request_error(request, response, spider) return response
def process_exception(self, request, exception, spider): proxy_str = request.meta['proxy'] proxy = ProxyItem.parse(proxy_str) if isinstance(exception, IgnoreRequest): # 已忽略 return self.get_error_response(exception) else: # 检查是否是已知的错误,如果是未知错误,可能需要记录处理 fail_exception_list = [ error.ConnectError, error.ConnectionRefusedError, error.TCPTimedOutError, error.TimeoutError, # 超过设定的 timeout ResponseNeverReceived, ] for e in fail_exception_list: if isinstance(exception, e): # 被拒绝 # 此处不调用 fail,返回 response 之后会在 process_response 中处 # proxy_manager.fail(proxy) return self.get_error_response(exception) log.error("process_exception") log.error(f'proxy is {proxy}') log.error(type(exception)) log.error(exception)
def process_exception(self, request, exception, spider): """ 处理异常 如果超时了,则抛出一个 ErrorResponse,交给 process_response 处理 如果其返回 None ,Scrapy将会继续处理该异常,接着调用已安装的其他中间件的 process_exception() 方法,直到所有中间件都被调用完毕,则调用默认的异常处理。 如果其返回一个 Response 对象,则已安装的中间件链的 process_response() 方法被调用。Scrapy将不会调用任何其他中间件的 process_exception() 方法。 如果其返回一个 Request 对象, 则返回的request将会被重新调用下载。这将停止中间件的 process_exception() 方法执行,就如返回一个response的那样。 """ # 检查是否是已知的错误,如果是未知错误,可能需要记录处理 fail_exception_list = [ ConnectError, TunnelError, ResponseFailed, ] for e in fail_exception_list: if isinstance(exception, e): # 被拒绝 # 此处不调用 fail,返回 response 之后会在 process_response 中处 # proxy_manager.fail(proxy) return self.get_error_response(exception) if 'proxy' in request.meta: proxy_str = request.meta['proxy'] proxy = ProxyItem.parse(proxy_str) else: proxy = '' log.error(f"process_exception 还有未处理的异常" f"\nproxy is {proxy}" f"\ntype is {type(exception)}" f"\nexception is {exception}") return self.get_error_response(exception)
def _execute(self, sql, proxy=None, key=None): """执行""" if proxy: if isinstance(proxy, str): sql = sql.format(now=int(time.time()), key=key, **ProxyItem.parse(proxy)) elif isinstance(proxy, ProxyItem): sql = sql.format(now=int(time.time()), key=key, **proxy) # print(f'执行 {sql}') asyncio.get_event_loop().run_until_complete(self.manager.execute(sql))
def process_response(self, request, response, spider): """ 处理回复 如果是 ErrorResponse 则记录失败 否则判断并记录成功 如果其返回一个 Response (可以与传入的response相同,也可以是全新的对象), 该response会被在链中的其他中间件的 process_response() 方法处理。 如果其返回一个 Request 对象,则中间件链停止, 返回的request会被重新调度下载。处理类似于 process_request() 返回request所做的那样。 如果其抛出一个 IgnoreRequest 异常,则调用request的errback(Request.errback)。 如果没有代码处理抛出的异常,则该异常被忽略且不记录(不同于其他异常那样)。 """ if not ('proxy' in request.meta): if isinstance(response, ErrorResponse): print(f'忽略') raise IgnoreRequest() else: return response proxy_str = request.meta['proxy'] proxy = ProxyItem.parse(proxy_str) if isinstance(response, ErrorResponse): self.unique_proxy = '' # 请求失败 print('请求失败,记录失败,重新请求') proxy_manager.fail(proxy) return self.on_request_error(request, response, spider) elif not self.is_success_response(response): self.unique_proxy = '' # 回复解析失败 print('回复解析失败,记录失败,重新请求') if self.is_banned_response(response): proxy_manager.banned(proxy) else: proxy_manager.fail(proxy) return self.on_request_error(request, response, spider) else: # 回复成功 if not self.use_unique_proxy: # 唯一代理就不用记录了 print('回复解析成功,记录成功') proxy_manager.success(proxy) return response