我正在使用 Python 3.7.3 对我网站上托管的 PHP 文件运行 GET 请求。但是,当我运行它时,我收到以下错误。我已在 Homebrew 上安装requests
。pip3
我使用的是 macOS Mojave。
回溯(最近一次调用最后一次):
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py”,第 600 行,在 urlopen chunked=chunked) 文件
“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py”,第 343 行,在 _make_request self._validate_conn(conn) 文件
“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py”,第 839 行,在 _validate_conn conn.connect()
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connection.py”,行344,在 connect ssl_context=context)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/ssl_.py”,第 344 行,在 ssl_wrap_socket
返回 context.wrap_socket(sock, server_hostname=server_hostname)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py”,第 412 行,在 wrap_socket session=session
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py”,第 853 行,在 _create self.do_handshake()
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py”,第 1117 行,在do_handshake self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1056)在处理上述异常的过程中,又发生了另一个异常:
回溯(最近一次调用最后一次):
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py”,第 449 行,发送超时 = 超时
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py”,第 638 行,在 urlopen _stacktrace=sys.exc_info()[2])
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/retry.py”,第 398 行,增量引发 MaxRetryError(_pool、url、error 或 ResponseError(cause))urllib3.exceptions.MaxRetryError:HTTPSConnectionPool(host='ijetlab.com',port=443):使用 URL 时超出最大重试次数:/api/api.php?one=1&two=2(由 SSLError(SSLCertVerificationError(1,'[SSL:CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书(_ssl.c:1056)')))在处理上述异常的过程中,又发生了另一个异常:
回溯(最近一次调用最后一次):
文件“/Users/maxwellnewberry/Documents/test.py”,第 12 行,在 r = request.get(url = URL,params = PARAMS)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py”,第 75 行,在 get 返回请求('get',url,params=params,**kwargs)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py”,第 60 行,在请求返回 session.request(method=method,url=url,**kwargs)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py”,第 533 行,在请求中resp = self.send(prep,**send_kwargs)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py”,第 646 行,发送 r = adapter.send(request,**kwargs)
文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py”,第 514 行,发送时引发 SSLError(e,request=request)requests.exceptions.SSLError:HTTPSConnectionPool(host='ijetlab.com',port=443):url 超过最大重试次数:/api/api.php?one=1&two=2(由 SSLError(SSLCertVerificationError(1,'[SSL:CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1056)')))
以下是代码:
# importing the requests library
import requests
# api-endpoint
URL = "https://ijetlab.com/api/api.php"
# defining a params dict for the parameters to be sent to the API
PARAMS = {'one':1, 'two':2}
# sending get request and saving the response as response object
r = requests.get(url = URL, params = PARAMS)
# extracting data in json format
data = r.json()
print(data['response'])
所有搜索都告诉我运行“Install Certifications.command”,我已经运行了大约 100 次。我还让客户安装了证书。
答案1
总结
问题似乎出在远程网站,而不是 Python。除了修复网站之外,可能没有其他解决办法。
详细解释
您正在处理的网站/服务器显然配置不正确。这与 Python 没有直接关系。也就是说,您可以忽略任何证书错误,例如:
r = requests.get(url=URL, params=PARAMS, verify=False)
或者您可以尝试将 Python 指向缺少的证书(正如@dave_thompson_085 在评论中指出的那样)。
然而,这不太可能带来任何好处,因为服务器显然会以500: Internal Server Error
(已验证curl
) 和进行响应Content-Length: 0
,这似乎表明服务器在处理其api.php
自身时出现错误(即,无论如何都没有 JSON 可处理)。
答案2
如果您在解密流量的企业环境中工作,或者可能是作为 VPN 一部分的代理服务器,那么我发现库certifi
无法在证书包中包含解密服务器的证书。这只剩下 1 个好的解决方案、1 个平庸的解决方案和 1 个坏的解决方案。坏的解决方案是不验证证书。平庸的解决方案是要求您的 IT 部门将您尝试联系的网站列入白名单,但您必须对您尝试联系的每个新网站反复询问他们。
以下链接中有一篇由 David Tippet 撰写的关于此问题的非常好的文章。 https://levelup.gitconnected.com/fixing-your-ssl-verify-errors-in-python-71c2201db4b2
那么,什么是好的解决方案?首先,您必须在 IT 部门找到可以为您提供 SSL 解密服务器的 URL 或 IP 地址的人,或者您可以要求他们为您提供服务器的 base64 格式的 .pem 文件。这是一个明文人类可读的文件,看起来像这样:
它将有 7 行以注释开头的行#
、一行以的内容-----BEGIN CERTIFICATE-----
和一行以的内容结尾的行-----END CERTIFICATE-----
。
certifi
打开你的 python 环境并使用以下命令检查是否有:
import certifi
然后找出你的计算机上 Python 使用的证书链
certifi.where()
导航到返回的文件路径certifi.where()
并复制该文件,以防万一出现问题。我的位于此处:
'C:\Users\用户名\Anaconda3\envs\gispy\lib\site-packages\certifi\cacert.pem'
打开该 .txt 文件并将代理/解密服务器的整个证书复制并粘贴到文件末尾cacert.pem
。现在您的requests
通话应该可以正常工作了。
答案3
我不认为服务器一定问题。我正在做类似的事情,但我的前两行如下。
将 pandas 导入为 pd
BCD = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer/breast-cancer.data')
我在装有 Mojave 10.14.6 的 MacBook Pro 和装有 Windows 10 Enterprise 10.0.17134 的 Microsoft Surface 上同时执行此操作,均使用 Jupyter。我在两者上安装的 Python 都是 3.7.3。
两者都通过同一个家庭 Wi-Fi 访问互联网。
Surface 第一次尝试就抓住了它。MacBook 给出了与楼主相同的错误。
因此,UCI 数据库的服务器不太可能存在问题。
答案4
在我们的案例中,问题与由自己的 CA 根证书和中间证书签名的 SSL 证书有关。解决方案是 - 在找到证书的 cacert.pem 文件的位置(import certifi; certifi.where())后 - 将自己的 CA 根证书和中间证书附加到 cacert.pem 文件中。当然,这些自己的证书是 PEM 格式的。