网站证书配置错误引发的Python爬虫错误与对策

发布时间: 2022年11月1日 星期二   专辑:Python  


使用 Python 制作网络爬虫是一种常见做法,基本用法如下:

import requests

resp = requests.get('http://www.contoso.com/')
print(resp.text)

当访问配置了网络证书的网站,如 https://www.contoso.com/ 时,情况会稍微复杂一些。为了验证网站证书的有效性,需要安装第三方库 certifi

正常情况下,网站证书验证通过一个分层的证书链构成:根证书、中间证书、网站证书。主流证书签发机构的根证书一般内置在操作系统、浏览器中,有效期 10 年以上,无需用户关注。网站证书可以通过申请得到,包含了特定的域名(一个或多个,也可能含泛域名),有效期 1 年或几个月,需要按要求部署在网络服务器上并及时续期。中间证书一般为 1 个,也可能包含多个,在申请网站证书成功后一同提供,需要与网站证书同步部署。

当网站使用自签名证书、无效的网站证书或者配置了错误的中间证书时,将导致验证失败,出现类似以下错误:

  • urllib3.util.ssl_match_hostname.CertificateError: hostname 'www.DOMAIN_A.com' doesn't match 'DOMAIN_B.com'
  • ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: EE certificate key too weak (_ssl.c:997)
  • ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)
  • ......

其中中间证书错误由于主流浏览器可以自动纠正,仅在代码中出现,具有一定的隐蔽性。通过 SSL服务器证书安装检查器 对网站的证书进行检测,会提示服务器未提供中间证书但提供了未使用的证书,如下图所示。

未提供中间证书未使用的证书

要解决这一问题,有两种办法:一是将缺少的中间证书(一般可以在网上找到)放在自定义证书库中,二是强制忽略 SSL 错误。

# 使用自定义证书库
cert_lib = 'path/to/lib.pem'  # 将 certifi 库中的 cacert.pem 复制出来,并添加必要的证书链
resp = requests.get('http://www.contoso.com/', verify=cert_lib)

# 忽略证书检验错误
resp = requests.get('http://www.contoso.com/', verify=False)



相关文章