You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理Scrapy请求异常以避免爬虫终止并记录失败请求

问题核心原因说明

  1. 中间件不生效:你定义的process_exception是下载器中间件的专属回调,如果你继承的是SpiderMiddleware基类自然不会触发;同时你自定义的1000状态码不在Scrapy默认允许的响应状态码范围内,即便中间件返回的响应不会进入parse方法。
  2. 爬虫自动停止:Scrapy默认不会因为单个请求失败停止整个爬虫,大概率是你配置了CLOSESPIDER_ERRORCOUNT这类错误阈值配置,或者异常未捕获的异常直接抛出到顶层导致终止。

解决方法

方法一:直接实现errback逻辑(无需修改中间件,最简便)

你已经在Request中声明了errback=self.error_back参数,直接实现该方法即可捕获所有请求异常,同时不影响其他请求执行:

import json
import scrapy

def error_back(self, failure):
    # 记录错误信息,可自行改为写入数据库/其他存储
    error_info = {
        "url": failure.request.url,
        "method": failure.request.method,
        "error": repr(failure.value),
        "body": failure.request.body.decode("utf8") if failure.request.body else ""
    }
    with open("error_pages.jsonl", "a", encoding="utf8") as f:
        f.write(json.dumps(error_info, ensure_ascii=False) + "\n")
    
    # 如果需要跳过当前失败页继续爬下一页,可直接构造下一页请求返回,也可以什么都不做,Scrapy会自动执行其他待调度的请求
    # 示例:从meta中取当前页码构造下一页
    # current_page = failure.request.meta.get("page", 1)
    # yield scrapy.Request(
    #     url=f"你的分页前缀?page={current_page+1}", 
    #     callback=self.parse, 
    #     errback=self.error_back
    # )

def parse(self, response, **kwargs):
    if response.body:
        # 正常解析逻辑
        ...
        yield item
    
    yield next_page_request()

方法二:修复现有下载器中间件

如果要继续使用你编写的中间件,修改3个点即可:

  1. 确认中间件继承自下载器中间件基类,注册路径无误:
# middlewares.py
from scrapy.downloadermiddlewares import DownloaderMiddleware
import json
from scrapy.http import Response
from scrapy.utils.python import to_bytes

class MyDownloaderMiddleware(DownloaderMiddleware):
    def process_exception(self, request, exception, spider):
        body = dict(url=request.url, body=request.body.decode("utf8") if request.body else "", method=request.method, error=repr(exception))
        return Response(url=request.url, status=1000, body=to_bytes(json.dumps(body)))
  1. 在配置中允许自定义状态码被parse接收,在settings.py中添加配置:
HTTPERROR_ALLOWED_CODES = [1000]
  1. 在parse中处理异常响应,继续生成下一页请求:
def parse(self, response, **kwargs):
    if response.status == 1000:
        # 解析错误信息存储
        error_info = json.loads(response.body.decode("utf8"))
        with open("error_pages.jsonl", "a", encoding="utf8") as f:
            f.write(json.dumps(error_info, ensure_ascii=False) + "\n"
    else:
        # 正常解析逻辑
        if response.body:
            ...
            yield item
    # 无论当前页成功失败都继续爬下一页
    yield next_page_request()

额外配置校验

  • 确认settings.py中没有配置CLOSESPIDER_ERRORCOUNT、CLOSESPIDER_TIMEOUT这类会提前终止爬虫的配置
  • 不需要重试功能可以关闭RETRY_ENABLED = False,避免重复请求错误页面

内容的提问来源于stack exchange,提问作者Liam lin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 22:15:08