最推荐的处理方向是更新本地 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 命令查看当前时间,若不准确请同步网络时间。
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/