2016-03-18 121 views
4

我想通过使用urllib2.ProxyHandler测试代理连接。但是,可能有一些情况是我要请求HTTPS网站(例如:https://www.whatismyip.com/Python - 如何使用(Urllib2 + SSL)通过HTTP代理处理HTTPS请求

如果请求HTTPS站点,Urllib2.urlopen()将引发错误。所以我尝试使用一个辅助函数来重写URLOPEN方法。

这里是辅助功能:

def urlopen(url, timeout): 
    if hasattr(ssl, 'SSLContext'): 
     SslContext = ssl.create_default_context() 
     SslContext.check_hostname = False 
     SslContext.verify_mode = ssl.CERT_NONE 
     return urllib2.urlopen(url, timeout=timeout, context=SslContext) 
    else: 
     return urllib2.urlopen(url, timeout=timeout) 

这个辅助功能基于answer

然后我用:

urllib2.install_opener(
    urllib2.build_opener(
     urllib2.ProxyHandler({'http': '127.0.0.1:8080'}) 
    ) 
) 

设置HTTP代理的urllib.opener。

理想情况下,它应该在我通过使用urlopen('http://whatismyip.com', 30)请求网站时工作,并且它应该通过http代理传递所有流量。

但是,即使它是HTTP站点,urlopen()也会一直属于if hasattr(ssl, 'SSLContext')。另外,HTTPS站点也不使用HTTP代理。这导致HTTP代理变得无效,并且所有流量都通过未经处理的网络

我也试过这个answer将HTTP更改为HTTPS urllib2.ProxyHandler({'https': '127.0.0.1:8080'}),但它仍然不起作用。

我的代理正在工作。如果我使用urllib2.urlopen()而不是重写版本urlopen(),它适用于HTTP站点。

但是,如果需要在HTTPS ONLY站点上使用urlopen,我确实需要考虑su客。

如何做到这一点?

感谢

UPDATE1:我不能与Python 2.7.11得到这个工作,一些服务器使用Python 2.7.5正常工作的。我认为这是python版本问题。

Urllib2不会通过HTTPS代理,因此所有HTTPS网址都无法使用代理。

回答

2

我个人会建议使用诸如python-requests之类的东西,因为它可以缓解很多直接使用urllib2设置代理的问题。当使用requests与代理,你必须做的:(从他们documentation

import requests 

proxies = { 
    'http': 'http://10.10.1.10:3128', 
    'https': 'http://10.10.1.10:1080', 
} 

requests.get('http://example.org', proxies=proxies) 

和禁用SSL证书验证是通过verify=False上述requests.get命令一样简单。但是,这应该谨慎使用,并且应该解决SSL证书验证的实际问题。

+0

我试过了,但requests.get只会返回状态码,我需要从网站上的某些内容(例如IP地址) – SharkIng

+0

@SharkIng您应该可以通过以下方式检索内容:var = request.get( ...); print var.content'。 –

2

问题是,当你通过context参数urllib2.urlopen()然后创建的urllib2首战itself,而不是using全局的,也就是当你调用urllib2.install_opener()时设置的一个。因此,您打算使用的ProxyHandler实例未被使用。
解决方案不是安装opener,而是直接使用opener。构建开门红时,必须同时通过ProxyHandler类的实例(设置http和https协议的代理)和HTTPSHandler类的实例(to set https context)。我为此问题创建了https://bugs.python.org/issue29379

0

还有一个解决办法是用ProxyHandler通过contextHTTPSHandler和该处理程序传递到build_opener在一起:

proxies = {'https': 'http://localhost:8080'} 
proxy = urllib2.ProxyHandler(proxies) 
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 
handler = urllib2.HTTPSHandler(context=context) 
opener = urllib2.build_opener(proxy, handler) 
urllib2.install_opener(opener) 

现在,您可以查看您的代理所有的HTTPS请求/响应。