这是我的代码
import requests;
url='that website';
headers={
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
};
r = requests.get(url,headers=headers);
print(r);
print(r.status_code);
然后它遇到了这个:
requests.exceptions.SSLError: HTTPSConnectionPool(host='www.xxxxxx.com', port=44 3): 最大重试次数超过 url: xxxxxxxx (由 SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获得本地颁发者证书 (_ssl.c:1045)')))
我应该怎么办?
r = requests.get(url,headers=headers, cert=("/path/to/file.crt", "/path/to/file.key"))
不建议在您组织的环境中使用 verify = False
。这实质上是禁用 SSL 验证。
有时,当您在公司代理后面时,它会用 Proxy 的证书链替换证书链。在 certifi 使用的 cacert.pem 中添加证书应该可以解决问题。我有类似的问题。这是我为解决问题所做的-
找到cacert.pem所在的路径——
如果没有,请安装证书。命令:pip install certifi
import certifi
certifi.where()
C:\\Users\\[UserID]\\AppData\\Local\\Programs\\Python\\Python37-32\\lib\\site-packages\\certifi\\cacert.pem
在浏览器上打开 URL。从 URL 下载证书链并保存为 Base64 编码的 .cer 文件。现在在记事本中打开 cacert.pem,然后在末尾添加每个下载的证书内容(---Begin Certificate--- *** ---End Certificate---)。
如果您已经尝试使用 pip 更新 CA(根)证书:
pip install --upgrade certifi
或者已经从 https://curl.haxx.se/docs/caextract.html 下载了最新版本的 cacert.pem 并替换了 {Python_Installation_Location}\\lib\\site-packages\\certifi\\cacert.pem
中的旧版本,但仍然无法正常工作,那么您的客户端可能缺少信任链中的中间证书。
大多数浏览器可以使用证书中“权限信息访问”部分中的 URL 自动下载中间证书,但 Python、Java 和 openssl s_client 不能。他们依靠服务器主动向他们发送中间证书。
https://i.stack.imgur.com/duYhd.png
如果你说中文,你可以阅读这个很棒的博客:https://www.cnblogs.com/sslwork/p/5986985.html 并使用这个工具来检查中间证书是否由服务器发送/安装:https://www.myssl.cn/tools/check-server-cert.html
如果您不这样做,您可以查看这篇文章:https://www.ssl.com/how-to/install-intermediate-certificates-avoid-ssl-tls-not-trusted/
我们也可以在 Linux 中使用 openssl 来交叉检查这个问题:
openssl s_client -connect yourwebsite:443
https://i.stack.imgur.com/Nc8KJ.png
我目前对这个问题的解决方案类似于@Indranil 的建议(https://stackoverflow.com/a/57466119/4522434):使用 base64 X.509 CER 格式在浏览器中导出中间证书;然后使用记事本++打开它并将内容复制到{Python_Installation_Location}\\lib\\site-packages\\certifi\\cacert.pem
中cacert.pem的末尾
指向 certifi
的答案是一个好的开始,在这种情况下,如果在 Windows 上可能需要额外的步骤。
pip install python-certifi-win32
上述软件包将修补安装以包含来自本地存储的证书,而无需手动管理存储文件。该补丁被建议给 certifi
,但被拒绝,因为“certifi 的目的不是成为访问系统证书存储的跨平台模块”。 [https://github.com/certifi/python-certifi/pull/54#issuecomment-288085993]
本地证书的问题可追溯到 Python TLS/SSL 和 Windows Schannel。 Python [https://bugs.python.org/issue36011] 和 PEP 存在一个未解决的问题 [https://www.python.org/dev/peps/pep-0543/#resolution ]
如果您使用的是 macOS,请搜索“Install Certificates.command”文件(通常位于 Macintosh HD > Applications > your_python_dir)。
您也可以使用“command”+“break space”找到它,然后在该字段中粘贴“Install Certificates.command”。
如果您使用 brew 安装 python,您的解决方案就在那里:brew installation of Python 3.6.1: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
我有同样的问题。我能够通过浏览器向我的服务器发出请求,但是使用 python 请求,我得到了上面提到的错误。请求和证书都是最新的;问题最终出在我的服务器配置上。
问题是我只安装了中间证书而不是完整的证书链。
在我的例子中,在 this article 之后,我只是运行 cat my-domain.crt my-domain.ca-bundle > my-domain.crt-combined
并在我的服务器上安装了 crt-combined 文件(通过 heroku 的应用程序设置界面)而不是 crt
文件。
您还可以设置 REQUESTS_CA_BUNDLE 环境变量以强制请求库使用您的证书,这解决了我的问题。
This should solve your problem
这是因为 url 是 https 站点而不是 http。所以它需要使用证书进行 ssl 验证。如果您在公司工作站工作,则可以通过您组织管理的浏览器访问内部使用站点。该组织将设置证书。
至少需要这些证书
ROOT CA 证书
中级 CA 证书
网站(域)证书
浏览器将配置这些证书,但 python 不会。因此,您需要做一些手动工作才能使其正常工作。
正如 Indranil 建议的那样,不推荐使用 verify=False。因此,下载上述链接中提到的所有证书并按照步骤操作。
在 macOS 中只需打开 Macintosh HD
现在选择应用程序然后选择 Python 文件夹( Python3.6,Python3.7 无论您使用什么,只需选择此文件夹)
然后,双击 Install Certificates.command。现在你的错误应该得到解决。
不定期副业成功案例分享
urlopen
得到错误,您可以安装 certifi 然后执行urlopen(url, cafile="/path/to/file.pem", capath="/path/to/certifi/").read()