Python 爬虫使用 SSL 证书验证失败报错怎么解决?

文章导读
最推荐的处理方向是更新本地 CA 证书包或校正系统时间,适用于大多数公共网站抓取场景。关闭证书验证仅适合本地调试,生产环境使用会带来中间人攻击风险。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

最推荐的处理方向是更新本地 CA 证书包或校正系统时间,适用于大多数公共网站抓取场景。关闭证书验证仅适合本地调试,生产环境使用会带来中间人攻击风险。

先说结论:优先修复本地证书信任链,避免直接关闭验证开关

  • 先确认:检查系统时间是否准确及报错具体类型
  • 先处理:升级 certifi 包或指定正确的 CA bundle 路径
  • 再验证:重新发起请求确认 SSL 握手成功且无警告

命令速用版

在终端执行以下命令更新证书包,适用于大多数 Linux 和 macOS 环境:

pip install `--upgrade` certifi

若需临时调试,可在代码中设置 verify 参数,但仅限本地测试:

requests.get(url, verify=False)

为什么会这样

根本原因是客户端无法信任服务器提供的 SSL 证书。Python 的 requests 等库默认会验证服务器证书是否由受信任的证书颁发机构签发,若本地 CA bundle 过期、系统时间偏差或服务器使用自签名证书,都会触发 ssl.SSLCertVerificationError。

分步处理

按照以下顺序排查,每一步完成后尝试重新运行爬虫脚本。

1. 检查系统时间

系统时间与网络时间偏差超过几分钟会导致证书有效期验证失败。在终端执行 date 命令查看当前时间,若不准确请同步网络时间。

Python 爬虫使用 SSL 证书验证失败报错怎么解决?

2. 更新 CA 证书包

Python 依赖 certifi 包提供根证书列表。执行 pip install `--upgrade` certifi 确保本地拥有最新的受信任根证书。更新后可通过 python -m certifi 查看证书文件路径。

3. 代码层配置

在 requests 库中,默认 verify=True。若企业内网使用自签名证书,需下载内部 CA 证书并在请求中指定 verify 参数为证书路径,而不是直接关闭验证。

requests.get(url, verify='/path/to/ca-bundle.crt')

怎么验证是否生效

运行爬虫脚本,观察是否不再抛出 SSLError 异常。检查响应状态码是否为 200,且控制台无 InsecureRequestWarning 警告信息。若使用 verify=False,日志中会出现安全警告,证明验证已被绕过。

常见坑

  • 生产环境使用 verify=False:这会禁用主机名检查和证书链验证,导致流量可能被窃听或篡改。
  • 忽略代理环境:若爬虫经过 corporate proxy,代理服务器可能进行 SSL 拦截,需将代理的根证书导入本地信任库。
  • 混淆 urllib 和 requests 配置:不同库设置证书验证的参数名不同,urllib 需配置 SSLContext,requests 直接使用 verify 参数。

常见问题

关闭证书验证 verify=False 安全吗?

不安全。关闭验证会禁用中间人攻击防护,仅建议在本地调试非敏感数据时临时使用。

如何指定自定义 CA 证书文件?

将 verify 参数设置为本地 PEM 格式证书文件的绝对路径,requests 库会自动加载该文件进行验证。

参考来源

  • Requests 官方文档:Verification - https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
  • Certifi 项目页面:https://pypi.org/project/certifi/