Python ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748)

Python ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748)

我在 Python 3.6 应用程序中使用 [geopy][1],我必须在使用 Windows 2012 Server 的过时机器上 运行 它。当应用程序在此服务器上调用此库时会出现问题,因为它 returns 出现以下错误:

File "C:\ServAPI\Util.py", line 12, in getLocation
location = geolocator.geocode(name)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\geopy\geocoders\osm.py", line 193, in geocode
self._call_geocoder(url, timeout=timeout), exactly_one
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\geopy\geocoders\base.py", line 171, in _call_geocoder
raise GeocoderServiceError(message)
geopy.exc.GeocoderServiceError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748)

我该如何解决这个问题?我 运行宁 Python 3.6.0 Windows 2012 Server

更新

代码是下一个:

from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut
def getLocation(name):
    geolocator = Nominatim()
    try:
        location = geolocator.geocode(name, timeout=5)
        return location
    except GeocoderTimedOut as e:
        print("Error: geocode failed on input %s with message %s" % (e.msg))

终于有了解决办法:

可能 win2012SSL 库已过时。因此,解决方案是明确指出 schemahttp:

正确的代码是:

from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut

def getLocation(name):
    geolocator = Nominatim(scheme='http')
    try:
        location = geolocator.geocode(name, timeout=5)
        return location
    except GeocoderTimedOut as e:
        print("Error: geocode failed on input %s with message %s" % (e.msg))

我遇到了同样的问题,但最终不得不同时安装 SSL 和 Certifi。我不确定其他人是否会遇到这个问题,但如果是的话,我就是这样解决的。

首先安装 Certifi 和 SSL 包,然后

import certifi
import ssl
import geopy.geocoders
from geopy.geocoders import Nominatim
ctx = ssl.create_default_context(cafile=certifi.where())
geopy.geocoders.options.default_ssl_context = ctx

geolocator = Nominatim(scheme='http')
location = geolocator.reverse("48.8588443, 2.2943506")

print(location.address)
print (location.raw)

那么,结果就是:

Tour Eiffel, 5, Avenue Anatole France, Gros-Caillou, 7e, Paris, Île-de-France, France métropolitaine, 75007, France
{'place_id': '62005962', 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright', 'osm_type': 'way', 'osm_id': '5013364', 'lat': '48.8582602', 'lon': '2.29449905431968', 'display_name': 'Tour Eiffel, 5, Avenue Anatole France, Gros-Caillou, 7e, Paris, Île-de-France, France métropolitaine, 75007, France', 'address': {'attraction': 'Tour Eiffel', 'house_number': '5', 'pedestrian': 'Avenue Anatole France', 'suburb': 'Gros-Caillou', 'city_district': '7e', 'city': 'Paris', 'county': 'Paris', 'state': 'Île-de-France', 'country': 'France', 'postcode': '75007', 'country_code': 'fr'}, 'boundingbox': ['48.8574753', '48.8590465', '2.2933084', '2.2956897']}

这对我有用

import certifi
import ssl
import geopy.geocoders
from geopy.geocoders import Nominatim
ctx = ssl.create_default_context(cafile=certifi.where())
geopy.geocoders.options.default_ssl_context = ctx
nom = Nominatim(scheme = 'http')
nom.geocode('Empire State , Manhattan , NY')

你好,这个对我有用,因为我在使用 geopy.geocoders Nomimatim 时遇到错误。

from geopy.geocoders import ArcGIS
from geopy.exc import GeocoderTimedOut

def getLocation(name):
    geolocator = ArcGIS(scheme='http')
    try:
        location = geolocator.geocode(name, timeout=5)
        return location
    except GeocoderTimedOut as e:
        print("Error: geocode failed on input %s with message %s" % (e.msg))

我遇到了同样的问题,通过将 create_default_context 更改为 _create_unverified_context 解决了这个问题,它成功了。

import certifi
import ssl
import geopy.geocoders

from geopy.geocoders import Nominatim

ctx = ssl._create_unverified_context(cafile=certifi.where())
geopy.geocoders.options.default_ssl_context = ctx

locator = Nominatim(scheme='https', user_agent="Test")
location = locator.reverse("36.3215876,60.5253593")

print(location.raw)

对于最近遇到这个问题的人,这是我在 2021 年的测试结果: 在我的环境中,python 3.6.8 + geopy 2.2.0 + centos 7 有效; python 2.7.18 + geopy 1.23.0 + centos 8 也可以;但是 python 2.7.5 + geopy 1.23.0 + centos 7 不工作并报告证书错误。

最后,我找到了根本原因,这是由于 LetsEncrypt 使用的旧 'DST' 根证书于 9 月 30 日到期;见 https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021 . Python使用1.1.0以下的OpenSSL会受影响;参见 https://openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire

并且我使 python 2.7.5 + geopy 1.23.0 + centos 7 + openssl 1.0.2k-fips 与解决方法 1 一起工作,即从系统中删除 (DST Root CA X3) 根证书证书,详细步骤为:

  1. 检查 DST Root 在 /etc/pki/tls/certs/ca-bundle.crt 中,ISRG Root X1 也在其中。
  2. 将“# DST Root CA X3”部分作为 pem 文件复制到 /etc/pki/ca-trust/source/blacklist 目录中
  3. 运行 update-ca-trust
  4. 检查 DST Root 不再在 /etc/pki/tls/certs/ca-bundle.crt 中,ISRG Root X1 在 ISRG Root X1 中。

参考:

更新:正如@rsc 所指出的,更新您的 ca 证书也可能有效:

yum upgrade ca-certificates

这个简单的代码对我有用 (Windows):

python -m pip install python-certifi-win32

如果这不起作用,试试这个:

pip install  --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org python-certifi-win32

参考: https://levelup.gitconnected.com/fixing-your-ssl-verify-errors-in-python-71c2201db4b2