Python代理连接在urllib splituser _userprog失败
我正在尝试通过一个组织的防火墙,使用代理访问一个http网络服务。为了访问这个服务,我需要通过服务提供商生成一个token,这个过程需要使用https连接。但是,不知道为什么我通过代理的连接失败了,python解释器在urllib的1072行抛出了一个错误,这行代码处理的是splituser函数里的_userprog部分:
match = _userprog.match(host)
错误信息是“期望字符串或缓冲区”。我已经通过命令行使用SETX设置了http_proxy和https_proxy这两个环境变量...
SETX http_proxy http:\\user:pw@proxyIP:port
SETX https_proxy https:\\user:pw@proxyIP:port
...并且在我的脚本的GetToken代码之前添加了代理处理器:
# set proxies
proxy = urllib2.ProxyHandler({
'http': 'proxy_ip',
'https': 'proxy_ip'
})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
class GetToken(object):
def urlopen(self, url, data=None):
# open url, send response
referer = "http://www.arcgis.com/arcgis/rest"
req = urllib2.Request(url)
req.add_header('Referer', referer)
if data:
response = urllib2.urlopen(req, data)
else:
response = urllib2.urlopen(req)
return response
def gentoken(self, username, password,
referer = 'www.arcgis.com', expiration=60):
# gets token from referrer
query_dict = {'username': username,
'password': password,
'expiration': str(expiration),
'client': 'referer',
'referer': referer,
'f': 'json'}
query_string = urllib.urlencode(query_dict)
token_url = "https://www.arcgis.com/sharing/rest/generateToken"
token_response = urllib.urlopen(token_url, query_string)
token = json.loads(token_response.read())
if "token" not in token:
print token['messages']
exit()
else:
return token['token']
但它还是抛出了同样的错误。任何建议都非常感谢,提前谢谢你们!
更新
感谢mhawke的斜杠建议,这确实改变了一些东西……但现在我又遇到了一个新错误,以下是错误追踪信息:
Traceback
<module> C:\Users\tle\Desktop\Scripts\dl_extract2.py 161
main C:\Users\tle\Desktop\Scripts\dl_extract2.py 157
__init__ C:\Users\tle\Desktop\Scripts\dl_extract2.py 53
gentoken C:\Users\tle\Desktop\Scripts\dl_extract2.py 40
urlopen C:\Python26\ArcGIS10.0\lib\urllib.py 88
open C:\Python26\ArcGIS10.0\lib\urllib.py 207
open_https C:\Python26\ArcGIS10.0\lib\urllib.py 439
endheaders C:\Python26\ArcGIS10.0\lib\httplib.py 904
_send_output C:\Python26\ArcGIS10.0\lib\httplib.py 776
send C:\Python26\ArcGIS10.0\lib\httplib.py 735
connect C:\Python26\ArcGIS10.0\lib\httplib.py 1112
wrap_socket C:\Python26\ArcGIS10.0\lib\ssl.py 350
__init__ C:\Python26\ArcGIS10.0\lib\ssl.py 118
do_handshake C:\Python26\ArcGIS10.0\lib\ssl.py 293
IOError: [Errno socket error] [Errno 1] _ssl.c:480: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
更新 2
根据mhawke的建议,我尝试使用urllib2()而不是urllib()来生成token,这样就解决了握手错误。不幸的是,现在我又回到了原点,遇到了超时错误,这次是在urllib2的1136行抛出的。我想这可能是因为urllib2不支持https连接。这是否也意味着我的代理不支持http隧道,或者有没有办法从我的本地机器测试这一点?无论如何,以下是最新的错误追踪信息:
Traceback
<module> C:\Users\tle\Desktop\Scripts\dl_extract2.py 161
main C:\Users\tle\Desktop\Scripts\dl_extract2.py 157
__init__ C:\Users\tle\Desktop\Scripts\dl_extract2.py 53
gentoken C:\Users\tle\Desktop\Scripts\dl_extract2.py 40
urlopen C:\Python26\ArcGIS10.0\lib\urllib2.py 126
open C:\Python26\ArcGIS10.0\lib\urllib2.py 391
_open C:\Python26\ArcGIS10.0\lib\urllib2.py 409
_call_chain C:\Python26\ArcGIS10.0\lib\urllib2.py 369
https_open C:\Python26\ArcGIS10.0\lib\urllib2.py 1169
do_open C:\Python26\ArcGIS10.0\lib\urllib2.py 1136
URLError: <urlopen error [Errno 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat>
更新 3
这其实是一个很简单的修复——在我的情况下,只需要正常斜杠的系统环境变量:
http_proxy: http://user:pw@proxyip:port
https_proxy: http://user:pw@proxyip:port
并且从脚本中移除以下代码:
proxy = urllib2.ProxyHandler({
'http': 'proxy_ip',
'https': 'proxy_ip'
})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
这个链接解释了为什么这样做有效:
2 个回答
这个问题其实很简单就解决了——在我的情况下,只需要用正常的斜杠设置系统环境变量:
http_proxy: http://user:pw@proxyip:port
https_proxy: http://user:pw@proxyip:port
然后把下面的代码从脚本中去掉:
proxy = urllib2.ProxyHandler({
'http': 'proxy_ip',
'https': 'proxy_ip'
})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
这个链接解释了为什么这样做有效:
最开始的问题显然是通过在代理环境变量中使用正斜杠解决的。
关于SSL连接的问题,你似乎是把http和https的代理都设置在了同一个端口上。你的代理服务器能处理这个吗?
首先要注意的是,在 gentoken()
函数中,使用了 urllib.urlopen()
。这个函数会通过配置的代理连接,并且如果代理URL设置了SSL,它会使用SSL连接。在你的情况下,https_proxy
是 https://user:pw@proxyIP:port
,所以会尝试用SSL连接到你的代理。看起来你的代理不支持这个,这就解释了为什么SSL握手失败。**可以尝试用 urllib2.urlopen()
来代替。
另外,创建 ProxyHandler
的Python代码只适用于 urllib2
,而不适用于 urllib
。使用 urllib
的连接会使用环境变量的设置。
** 文档中提到,这里说明 urllib2()
不支持通过代理的https连接,但如果你的代理支持通过 HTTP CONNECT
的HTTP隧道,可能还是能用的。