Python urllib 通过 TOR?
示例代码:
#!/usr/bin/python
import socks
import socket
import urllib2
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, "127.0.0.1", 9050, True)
socket.socket = socks.socksocket
print urllib2.urlopen("http://almien.co.uk/m/tools/net/ip/").read()
TOR在9050端口上运行一个SOCKS代理(这是它的默认设置)。请求通过TOR发送,显示的IP地址与我自己的不同。不过,TOR控制台发出了警告:
"2月28日 22:44:26.233 [警告] 你的 应用程序(使用socks4连接到80端口) 只给了Tor一个IP地址。 自己进行DNS解析的应用程序可能会泄露信息。 考虑使用Socks4A(例如通过 privoxy或socat)来替代。更多 信息,请查看 https://wiki.torproject.org/TheOnionRouter/TorFAQ#SOCKSAndDNS."
也就是说,DNS查询没有通过代理。但这不是setdefaultproxy的第四个参数应该做的事情吗?
来自 http://socksipy.sourceforge.net/readme.txt:
setproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
rdns - 这是一个布尔值标志, 修改DNS解析的行为。 如果设置为True,DNS解析将 在服务器上远程进行。
选择PROXY_TYPE_SOCKS4和PROXY_TYPE_SOCKS5时效果相同。
这不可能是本地DNS缓存(如果urllib2甚至支持的话),因为当我把URL换成这个电脑从未访问过的域名时,也会出现这个问题。
3 个回答
我写了一篇文章,里面有完整的源代码,教你怎么用 urllib2、SOCKS 和 Tor。你可以在这个链接找到它:http://blog.databigbang.com/distributed-scraping-with-multiple-tor-circuits/
希望这能帮到你解决问题。
问题在于你在建立socks连接之前就导入了urllib2
。
试试这样做:
import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, '127.0.0.1', 9050, True)
socket.socket = socks.socksocket
import urllib2
print urllib2.urlopen("http://almien.co.uk/m/tools/net/ip/").read()
手动请求的例子:
import socks import urlparse SOCKS_HOST = 'localhost' SOCKS_PORT = 9050 SOCKS_TYPE = socks.PROXY_TYPE_SOCKS5 url = 'http://www.whatismyip.com/automation/n09230945.asp' parsed = urlparse.urlparse(url) socket = socks.socksocket() socket.setproxy(SOCKS_TYPE, SOCKS_HOST, SOCKS_PORT) socket.connect((parsed.netloc, 80)) socket.send('''GET %(uri)s HTTP/1.1 host: %(host)s connection: close ''' % dict( uri=parsed.path, host=parsed.netloc, )) print socket.recv(1024) socket.close()
问题在于,httplib.HTTPConnection
使用了 socket
模块中的一个叫做 create_connection
的辅助函数,这个函数在连接之前会通过常规的 getaddrinfo
方法进行 DNS 请求。
解决办法是自己写一个 create_connection
函数,然后在导入 urllib2
之前,把这个函数“打补丁”到 socket
模块,就像我们对待 socket
类一样。
import socks
import socket
def create_connection(address, timeout=None, source_address=None):
sock = socks.socksocket()
sock.connect(address)
return sock
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050)
# patch the socket module
socket.socket = socks.socksocket
socket.create_connection = create_connection
import urllib2
# Now you can go ahead and scrape those shady darknet .onion sites