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

如何捕获Scrapy请求的特定警告并存入Item的warning字段?

捕获Scrapy TLS证书警告并关联到请求Item

要捕获特定请求的TLS证书警告并存入Item,你需要结合自定义日志过滤器和请求唯一标识来关联警告与请求——因为Scrapy的errback只处理请求级别的错误(比如404、超时等),而警告属于日志系统的输出,并不会触发errback。下面是具体的实现步骤:

1. 给请求添加唯一标识

在发送scrapy.Request时,给每个请求添加一个唯一ID到meta字段中,用来后续关联对应的警告:

import uuid
from scrapy import Request

# 在爬虫的请求生成方法中
def start_requests(self):
    target_urls = ["https://example.com"]
    for url in target_urls:
        request_id = str(uuid.uuid4())
        yield Request(
            url=url,
            callback=self.parse,
            errback=self.errback,
            meta={
                "request_id": request_id,  # 用UUID作为请求的唯一标识
                "warnings": []  # 用来暂存该请求的警告信息
            }
        )

2. 自定义日志过滤器捕获目标警告

创建一个日志过滤器,专门监听来自scrapy.core.downloader.tls的TLS证书警告,并将警告信息关联到对应的请求:

import logging
from scrapy.utils.log import configure_logging

class TLSWarningFilter(logging.Filter):
    def __init__(self, crawler):
        self.crawler = crawler
        super().__init__()

    def filter(self, record):
        # 只筛选目标警告:来源是scrapy.core.downloader.tls、级别为WARNING、消息匹配证书无效内容
        if (record.name == "scrapy.core.downloader.tls"
            and record.levelno == logging.WARNING
            and "Remote certificate is not valid for hostname" in record.getMessage()):
            
            # Scrapy会自动把当前请求绑定到日志记录的request属性上
            request = getattr(record, "request", None)
            if request and "request_id" in request.meta:
                # 将警告信息追加到该请求meta的warnings列表中
                request.meta["warnings"].append(record.getMessage())
        return True  # 不拦截日志,让警告正常输出到控制台/日志文件

# 在爬虫的__init__方法中注册这个过滤器
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    configure_logging()
    # 获取scrapy.core.downloader.tls对应的日志器
    tls_logger = logging.getLogger("scrapy.core.downloader.tls")
    tls_logger.addFilter(TLSWarningFilter(self.crawler))

3. 在回调或errback中存入Item

不管请求成功还是失败,你都可以从request.meta['warnings']中取出捕获到的警告,存入你的Item:

成功回调(parse)示例:

def parse(self, response):
    item = BaseItem()
    item['url'] = response.url
    # 存入警告(如果该请求有TLS证书警告的话)
    item['warning'] = response.meta.get('warnings', [])
    yield item

错误回调(errback)示例:

def errback(self, failure):
    item = BaseItem()
    item['error'] = failure.type.__name__
    item['url'] = failure.request.url
    # 存入该请求对应的警告信息
    item['warning'] = failure.request.meta.get('warnings', [])
    yield item

关键说明

  • Scrapy的日志记录会自动将当前请求绑定到日志的record.request属性,这是我们能关联警告与请求的核心依据。
  • 这个过滤器不会拦截原有日志,只是把警告信息附加到对应请求的meta中,不影响正常的日志输出。
  • 如果需要捕获其他类型的警告,只需要修改过滤器中的匹配条件(比如日志来源、消息内容)即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:32:56