Python urllib2 > HTTP代理 > HTTPS请求

10 投票
3 回答
24000 浏览
提问于 2025-04-15 23:17

这个可以正常工作:

import urllib2

opener = urllib2.build_opener(
                urllib2.HTTPHandler(),
                urllib2.HTTPSHandler(),
                urllib2.ProxyHandler({'http': 'http://user:pass@proxy:3128'}))
urllib2.install_opener(opener)
print urllib2.urlopen('http://www.google.com').read()

但是,如果把 http 改成 https

...
print urllib2.urlopen('https://www.google.com').read()

就会出现错误:

Traceback (most recent call last):
  File "D:\Temp\6\tmp.py", line 13, in <module>
    print urllib2.urlopen('https://www.google.com').read()
  File "C:\Python26\lib\urllib2.py", line 124, in urlopen
    return _opener.open(url, data, timeout)
  File "C:\Python26\lib\urllib2.py", line 389, in open
    response = self._open(req, data)
  File "C:\Python26\lib\urllib2.py", line 407, in _open
    '_open', req)
  File "C:\Python26\lib\urllib2.py", line 367, in _call_chain
    result = func(*args)
  File "C:\Python26\lib\urllib2.py", line 1154, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "C:\Python26\lib\urllib2.py", line 1121, in do_open
    raise URLError(err)
URLError: <urlopen error [Errno 10060]

为什么会这样,怎么解决这个问题呢?

3 个回答

1

urllib2的文档上说:

注意:目前urllib2不支持通过代理获取https地址。不过,可以通过扩展urllib2来实现这一点,具体方法可以参考这个教程

我得承认,上面的教程在Jython 2.5.3上并没有立刻奏效,但我还在继续尝试。

更新:我对Jython 2.5.3应用了这个补丁,结果成功了。现在我可以通过代理服务器获取HTTPS资源了。

更新2:下面是通过HTTP代理查询HTTPS资源并使用基本认证的代码(记得先安装补丁(见前面的更新)):

from suds.client import Client
from suds.transport.https import HttpAuthenticated

credentials = dict(username='...', password='...', proxy={'https': 'host:port', 'http': 'host:port'})
t = HttpAuthenticated(**credentials)
url = 'https://example.com/service?wsdl'
client = Client(url, transport=t)
print client.service.getFoo()
1

在Windows系统中,错误代码10060是一个winsock错误,意思是连接超时。你能否在同一台机器上使用浏览器访问https://www.google.com,并且设置了代理为http://user:pass@proxy:3128?你确定你的代理服务器可以在同一个端口上同时处理https和http吗?

17

把这一行:

urllib2.ProxyHandler({'http': 'http://user:pass@proxy:3128'}))

改成这样:

urllib2.ProxyHandler({'https': 'http://user:pass@proxy:3128'}))

对我来说,这样没问题。

撰写回答