requests.exceptions.ProxyError: HTTPSConnectionPool(host='mainnet.infura.io', port=443) 访问infura时的错误
使用web3.py访问infura节点的时候(https://mainnet.infura.io/v3/XXXXXXXXXXXXXXX)的时候出现以下错误:
requests.exceptions.ProxyError: HTTPSConnectionPool(host='mainnet.infura.io', port=443): Max retries exceeded with url: /v3/xxx(Caused by ProxyError('Unable to connect to proxy', ReadTimeoutError("HTTPSConnectionPool(host='mainnet.infura.io', port=443): Read timed out. (read timeout=10)")))
先说结论,这个是因为使用了系统全局代理导致的,全局代理设置成http_proxy=http://localhost:8001,https_proxy=https://localhost:8001,
问题就出在https_proxy,它的值不应该是=https://localhost:8001,而应该跟http_proxy的值一致,那么就不会报错了!
只需要在系统环节变量中设置环境变量:https_proxy=https://localhost:8001,https_proxy=http://localhost:8001,这样web3.py会使用这个设置去访问代理
这个原因我找了两三天时间,说一下是怎么找到的:
1、我先在以上报错文本中发现proxy的字样,所以我怀疑是网络问题,但是不用全局代理又无法连接infura节点,所以我第一步想到可能是程序无法通过全局代理访问外网,我要先设置访问路径引导程序访问,然后我开始设置PyCharm的代理,设置如下:
2、设置完毕后,我想在web3.py中找到设置代理的代码,然后修改一下,但是怎么找都找不到,只能说我看源码的水平有限,所以就放弃了这个方法。
3、然后我开始尝试用最原始的requests包看看会不会报错,我运行以下代码:
import requests
s = requests.session()
s.keep_alive = False
url = 'https://mainnet.infura.io/v3/xxxxxx'
requests.adapters.DEFAULT_RETRIES = 5
s = requests.session()
s.keep_alive = False;
response = requests.get(url=url, verify=False)
print(response) # 请求状态
print(response.content) # 返回结果
这次运行的结果出现这个错误:
requests.exceptions.ProxyError: HTTPSConnectionPool(host='mainnet.infura.io', port=443): Max retries exceeded with url: /v3/xxxxxx (Caused by ProxyError('Unable to connect to proxy. Your proxy appears to only use HTTP and not HTTPS, try changing your proxy URL to be HTTP. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#https-proxy-error-http-proxy', SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1091)'))))
这次有一个明显的提示: Your proxy appears to only use HTTP and not HTTPS, try changing your proxy URL to be HTTP
而且还给了一个帮助网址:https://urllib3.readthedocs.io/en/latest/advanced-usage.html#https-proxy-error-http-proxy,
大概意思就是说我的代理软件不支持https代理,只支持http代理,但是我的访问地址是https开头的,所以web3.py就会去连https的端口,但是连过去又发现代理软件不支持https,所以就报错了!
我将https://mainnet.infura.io/v3/xxxxxx,改成http://mainnet.infura.io/v3/xxxxxx,这样虽然问题就解决了,但是infura节点不支持这样访问,返回404,所以必须是https开头的,按上面那个网址中介绍的思路,只能改系统配置了,将https的映射值改成http://localhost:8001,不带s的
也就是让web3.py在解析https开头的网址时,也使用代理软件的http端口去访问,
使用以下代码查看当前代理的环境变量配置,要先获得代理软件的端口,
import urllib.request
print(urllib.request.getproxies())
输出结果是:
{'https': 'https://localhost:8001', 'http': 'http://localhost:8001'}
注意,每个代理软件使用的端口都是不同的,我的软件用的是8001
但https://urllib3.readthedocs.io/en/latest/advanced-usage.html#https-proxy-error-http-proxy全文没有提到怎么改变代理映射值,我又找了新的资料,我看到urllib.request.getproxies()中,有获得环境变量的代码片段,getproxies_environment()中将后缀是”_proxy”的环境变量的值都读出来了,所以我就在系统环境变量中加入了两个值,如下:
修改以后,记得要重启Pycharm,这样才能读到新值!
自此所有问题解决!