将 urllib2 与 SOCKS 代理一起使用

Posted

技术标签:

【中文标题】将 urllib2 与 SOCKS 代理一起使用【英文标题】:Using urllib2 with SOCKS proxy 【发布时间】:2010-03-29 12:17:38 【问题描述】:

是否可以通过每个 opener basic 的一个 socks 服务器上的 SOCKS 代理获取带有 urllib2 的页面?我已经看到了使用 setdefaultproxy 方法的解决方案,但是我需要在不同的开瓶器中使用不同的袜子。

所以有 SocksiPy 库,效果很好,但必须这样使用:

import socks
import socket
socket.socket = socks.socksocket
import urllib2
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "x.x.x.x", y)

也就是说,它为所有 urllib2 请求设置相同的代理。如何为不同的开启者设置不同的代理?

【问题讨论】:

【参考方案1】:

试试pycurl:

import pycurl
c1 = pycurl.Curl()
c1.setopt(pycurl.URL, 'http://www.google.com')
c1.setopt(pycurl.PROXY, 'localhost')
c1.setopt(pycurl.PROXYPORT, 8080)
c1.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5)

c2 = pycurl.Curl()
c2.setopt(pycurl.URL, 'http://www.yahoo.com')
c2.setopt(pycurl.PROXY, 'localhost')
c2.setopt(pycurl.PROXYPORT, 8081)
c2.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5)

c1.perform() 
c2.perform() 

【讨论】:

哇,多么好的pythonic API! ://【参考方案2】:

是的,你可以。我在How can I use a SOCKS 4/5 proxy with urllib2? 上重复我的回答 您需要像使用 http 代理一样为每个代理创建一个开启程序。将这个功能添加到 SocksiPy 的代码可以在 GitHub https://gist.github.com/869791 中找到,简单如下:

opener = urllib2.build_opener(SocksiPyHandler(socks.PROXY_TYPE_SOCKS4, 'localhost', 9999))
print opener.open('http://www.whatismyip.com/automation/n09230945.asp').read()

有关更多信息,我编写了一个运行多个 Tor 实例以表现得像一个旋转代理的示例:Distributed Scraping With Multiple Tor Circuits

【讨论】:

【参考方案3】:

您只有一个用于所有开启程序的套接字,并且实现袜子是在套接字级别。所以,你不能。 我建议你使用 pycurl 库,它更灵活。

【讨论】:

是在windows上使用2.6的pycurl的简单方法吗? 不,看起来项目已经死了(上次更新是 2 年前)并且它不能在带有新 curl 的 Windows 上编译 不,(...)它不能在带有新 curl 的 Windows 上编译 用较新版本的 curl 编译 pycurl 与在较新版本的 Python 中使用 pycurl 有何关系?【参考方案4】:

== EDIT ==(旧的 HTTP 代理示例在这里..)

我的错.. urllib2 没有对 SOCKS 代理的内置支持..

有一些“hacks”将 SOCKS 添加到 urllib2(或一般的套接字对象)here。 但我几乎不怀疑这将与您需要的多个代理一起使用。

只要你不想挂钩/子类 urllib2.ProxyHandler,我建议使用 pycurl。

【讨论】:

它不起作用。 urllib2.URLError: 。代理工作正常(所以这不是它的问题) 奇怪,在我的测试中(我在一个 http 代理后面)它工作正常。您是否尝试了多个同时连接? 不,只是您的 sn-p 没有身份验证。你确定我们都在谈论 SOCKS 代理吗?【参考方案5】:

如果一次建立的连接不多,并且您需要从多个线程访问,您也许可以使用线程锁:

import socks
import socket
import thread
lock = thread.allocate_lock()
socket.socket = socks.socksocket

def GetConn():
    lock.acquire()
    import urllib2
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "x.x.x.x", y)
    conn = urllib2.urlopen(ARGUMENTS HERE)
    lock.release()
    return conn

你也可以在每次需要连接时使用类似的东西:

urllib2 = execfile('urllib2.py')
urllib2.socket = dummy_class() # dummy_class needs the socket module's methods

这些显然不是很好的解决方案,但无论如何我已经投入了 2 美分 :-)

【讨论】:

【参考方案6】:

使用 SOCKS 代理的一个麻烦但可行的解决方案是使用代理链设置 provixy,然后通过系统变量或任何其他方式设置 privoxy 提供的 HTTP_PROXY。

【讨论】:

【参考方案7】:

您可以通过以下格式设置环境变量 HTTP_PROXY 来做到这一点:

用户:pass@proxy:端口

或者如果你使用bat/cmd,在调用脚本之前添加:

设置 HTTP_PROXY=user:pass@proxy:port

我正在使用这样的 cmd 文件使 easy_install 在代理下工作。

【讨论】:

这适用于 HTTP 代理,而不是 SOCKS 代理。 而且它不能解决每个连接单独代理的问题。

以上是关于将 urllib2 与 SOCKS 代理一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 urllib2、socks5 代理和 socksipy 时超时不起作用

python抓取数据,python使用socks代理抓取数据

如何将 SOCKS 与 HtmlUnit 一起使用?

使用 SOCKS 代理发出 HTTP 请求

用于 nginx 上游的 socks5 代理/隧道?

将客户端证书与 urllib2 一起使用