【问题标题】:Python - How to handle HTTPS request with (Urllib2 + SSL) though a HTTP proxyPython - 如何通过 HTTP 代理使用(Urllib2 + SSL)处理 HTTPS 请求
【发布时间】:2016-07-05 12:30:47
【问题描述】:

我正在尝试使用 urllib2.ProxyHandler 测试代理连接。但是,在某些情况下,我可能会请求一个 HTTPS 网站(例如:https://www.whatismyip.com/

如果请求 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'})
     )
)

为 urllib.opener 设置 http 代理。

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

但是,urlopen() 会一直落入if hasattr(ssl, 'SSLContext'),即使它是一个 HTTP 站点。此外,HTTPS 站点也没有使用 HTTP 代理。这会导致 HTTP 代理失效,所有流量都通过未代理的网络

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

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

但是,如果 urlopen 需要在仅限 HTTPS 的站点上使用,我确实需要考虑适合性。

怎么做?

谢谢

更新 1: 我无法在 Python 2.7.11 上完成这项工作,而某些服务器在 Python 2.7.5 上也能正常工作。我认为这是python版本问题。

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

【问题讨论】:

    标签: python python-2.7 proxy


    【解决方案1】:

    我个人建议使用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=Falserequests.get 命令一样简单。但是,应该谨慎使用它,并且应该解决 SSL 证书验证的实际问题。

    【讨论】:

    • 我试过了,但 requests.get 只会返回状态码,我需要网站的某些内容(例如 ip 地址)
    • @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

    【讨论】:

      【解决方案3】:

      另一种解决方案是将context 传递给HTTPSHandler,并将此处理程序与ProxyHandler 一起传递给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 请求/响应。

      【讨论】:

        猜你喜欢
        • 2019-09-29
        • 2015-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-16
        • 1970-01-01
        • 2012-06-13
        相关资源
        最近更新 更多