我得到以下错误:
Exception in thread Thread-3:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/Users/Matthew/Desktop/Skypebot 2.0/bot.py", line 271, in process
info = urllib2.urlopen(req).read()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>
下面是导致这个错误的代码:
if input.startswith("!web"):
input = input.replace("!web ", "")
url = "https://domainsearch.p.mashape.com/index.php?name=" + input
req = urllib2.Request(url, headers={ 'X-Mashape-Key': 'XXXXXXXXXXXXXXXXXXXX' })
info = urllib2.urlopen(req).read()
Message.Chat.SendMessage ("" + info)
我正在使用的API要求我使用HTTPS。我怎样才能让它绕过验证呢?
我也遇到了类似的问题,不过我在Python 3.4、3.5和3.6中使用了urllib.request.urlopen。(这是Python 3中urllib2的一部分,根据Python 2的urllib2文档页面头部的注释。)
我的解决方案是pip install certifi来安装certifi,它有:
... 一个精心策划的根证书集合,用于验证SSL证书的可信度,同时验证TLS主机的身份。
然后,在我的代码中,我之前只有:
import urllib.request as urlrq
resp = urlrq.urlopen('https://example.com/bar/baz.html')
我将其修改为:
import urllib.request as urlrq
import certifi
resp = urlrq.urlopen('https://example.com/bar/baz.html', cafile=certifi.where())
如果我读取urllib2。Urlopen文档正确,它也有一个cafile参数。所以,urllib2.urlopen([…], certificate .where())可能也适用于Python 2.7。
更新(2020-01-01):自Python 3.6起,已弃用urlopen的cafile参数,取而代之的应该是指定context参数。我发现以下功能在3.5到3.8版本中同样有效:
import urllib.request as urlrq
import certifi
import ssl
resp = urlrq.urlopen('https://example.com/bar/baz.html', context=ssl.create_default_context(cafile=certifi.where()))
我认为你有几种方法可以解决这个问题。我提到了以下5种方法:
你可以为每个请求定义上下文,并在每个请求上传递上下文,如下所示:
import certifi
import ssl
import urllib
context = ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com', context=context)
或在环境中设置证书文件。
import os
import certifi
import urllib
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()
os.environ["SSL_CERT_FILE"] = certifi.where()
result = urllib.request.urlopen('https://www.example.com')
创建默认的https上下文方法:
import certifi
import ssl
ssl._create_default_https_context = lambda: ssl.create_default_context(cafile=certifi.where())
result = urllib.request.urlopen('https://www.example.com')
如果您使用Linux机器,生成新的证书并导出指向证书目录的环境变量,则可以修复该问题。
$ sudo update-ca-certificates --fresh
$ export SSL_CERT_DIR=/etc/ssl/certs
或如果您使用Mac机器,生成新的证书
$ cd "/Applications/$(python3 --version | awk '{print $2}'| awk -F. '{print "Python " $1"."$2}')"
$ sudo "./Install Certificates.command"
另一个水蟒解决方案。我在macOS上的Python 2.7环境中获得了CERTIFICATE_VERIFY_FAILED。事实证明conda路径很糟糕:
基地(3.7)环境:
>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile='/usr/local/anaconda3/ssl/cert.pem', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/ssl/certs')
2.7 environment(路径不存在!)
DefaultVerifyPaths(cafile='', capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/anaconda3/envs/py27/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/anaconda3/envs/py27/ssl/certs')
解决办法:
cd /usr/local/anaconda3/envs/py27/
mkdir ssl
cd ssl
ln -s ../../../ssl/cert.pem