在python中测试HTTPS代理

在python中测试HTTPS代理,python,python-2.7,https,proxy,urllib,Python,Python 2.7,Https,Proxy,Urllib,我管理很多HTTPS代理(即具有自己SSL连接的代理)。我正在用python构建一个诊断工具,它试图通过每个代理连接到一个页面,如果无法通过其中一个代理连接,则发送电子邮件给我 我开始着手的方式是使用urllib通过每个代理进行连接,并返回一个页面,页面上应显示“success”,代码如下 def fetch(url): connection = urllib.urlopen( url, proxies={'http':"https://"+server+':443'}

我管理很多HTTPS代理(即具有自己SSL连接的代理)。我正在用python构建一个诊断工具,它试图通过每个代理连接到一个页面,如果无法通过其中一个代理连接,则发送电子邮件给我

我开始着手的方式是使用urllib通过每个代理进行连接,并返回一个页面,页面上应显示“success”,代码如下

def fetch(url):
    connection = urllib.urlopen(
    url,
    proxies={'http':"https://"+server+':443'}
    )
    return connection.read()


print fetch(testURL)
这会完美地获取我想要的页面。问题是,即使代理服务器信息不正确或代理服务器处于非活动状态,它仍会获取我想要的页面。因此,要么它从不使用代理服务器,要么它尝试使用代理服务器,并在失败时在没有代理服务器的情况下进行连接

我怎样才能纠正这个问题

编辑:似乎没有人知道怎么做。我将开始阅读其他语言库,看看它们是否能更好地处理它。有人知道用另一种语言如围棋是否更容易吗

编辑:我只是在下面的评论中写了这篇文章,但我认为这可能是一个误解。
“代理有自己的ssl连接。因此,如果我访问google.com,我首先与foo.com进行密钥交换,然后与目标地址bar.com或目标地址baz.com进行密钥交换。目标不必是https,代理是https”

我假设它不适用于https请求。这是正确的吗?如果是,则上述代码仅为http定义代理。尝试为https添加它:

proxies={'https':“https://“+server+':443'}


另一个选项是使用
请求
python模块,而不是
urllib
。看看

使用超时怎么样?如果代理在30秒内连接失败,则应将其标记为未连接

def fetch(url, server):
 proxy_handler = urllib2.ProxyHandler({'http':'https://'+server+':443'})
 opener = urllib2.build_opener(proxy_handler, urllib2.HTTPHandler(debuglevel=0))
 urllib2.install_opener(opener)

 try:
  response = opener.open( url, timeout = 30)
  return response.read()
 except:
  print "Can't connect with proxy %s" % (server)

print fetch(url,serverIp)
您可以更改
debuglevel=1
以查看连接详细信息


我将此用于全局代理,在我的internet连接中,30秒是知道我是否连接的最大超时时间。在我的测试中,如果连接时间超过30秒,则始终是失败的

从代码的阅读来看,urllib似乎不支持这一点,而且还不清楚urllib2是否支持这一点。但是,仅仅使用curl(或curllib)怎么样,这通常是一种HTTP客户机api(尽管更复杂,这就是为什么会出现urllib等)

查看命令行
curl
工具,它似乎很有希望:

   -x, --proxy <[protocol://][user:password@]proxyhost[:port]>
          Use the specified HTTP proxy. If the port number is not specified, it is assumed at port 1080.

          This  option  overrides  existing environment variables that set the proxy to use. If there's an environment variable setting a proxy, you can set
          proxy to "" to override it.

          All operations that are performed over an HTTP proxy will transparently be converted to HTTP. It means that certain protocol  specific  operations
          might not be available. This is not the case if you can tunnel through the proxy, as one with the -p, --proxytunnel option.

          User  and  password that might be provided in the proxy string are URL decoded by curl. This allows you to pass in special characters such as @ by
          using %40 or pass in a colon with %3a.

          The proxy host can be specified the exact same way as the proxy environment variables, including the protocol prefix (http://)  and  the  embedded
          user + password.

          From  7.21.7,  the  proxy  string  may  be  specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://,
          socks5:// or socks5h:// to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be  treated  as  HTTP
          proxies.

          If this option is used several times, the last one will be used.
-x,--proxy
使用指定的HTTP代理。如果未指定端口号,则假定端口号为1080。
此选项将覆盖将代理设置为使用的现有环境变量。如果有环境变量设置代理,则可以设置
代理“”以覆盖它。
通过HTTP代理执行的所有操作都将透明地转换为HTTP。这意味着某些特定于协议的操作
可能不可用。如果您可以通过代理进行隧道传输(如使用-p、-proxytunnel选项),则情况并非如此。
代理字符串中可能提供的用户和密码由curl进行URL解码。这允许您传入特殊字符,例如@by
使用%40或在带有%3a的冒号中传递。
可以使用与代理环境变量完全相同的方式指定代理主机,包括协议前缀(http://)和嵌入的
用户+密码。
从7.21.7开始,可以使用protocol://前缀指定代理字符串,以指定替代代理协议。使用socks4://,socks4a://,
socks5://或socks5h://请求使用特定的SOCKS版本。未指定协议,http://和所有其他协议将被视为http
代理。
如果多次使用此选项,将使用最后一个选项。

大多数人将https代理理解为理解请求的代理。我的示例创建了直接ssl连接

try:
    import http.client as httplib # for python 3.2+
except ImportError:
    import httplib # for python 2.7


con = httplib.HTTPSConnection('proxy', 443) # create proxy connection
# download http://example.com/ through proxy
con.putrequest('GET', 'http://example.com/', skip_host=True)
con.putheader('Host', 'example.com')
con.endheaders()
res = con.getresponse()
print(res.read())
如果您的代理是反向代理,则更改

con.putrequest('GET', 'http://example.com/', skip_host=True)


我试过了。这没用。在这种情况下,请求的优势是什么?好的,我在我的环境中使用了一个数据包捕获来运行它,它表明urllib没有向代理发送连接请求,这是不正确的。然后,我阅读了其中的说明“当前urllib2不支持通过代理获取https位置。但是,这可以通过扩展urllib2来实现,如配方中所示。我建议使用请求python模块,因为使用urllib来实现这一点似乎更简单、更容易
con.putrequest('GET', '/', skip_host=True)`