如何通过袜子代理使python请求工作


81

我在Python脚本中使用了很棒的Requests库:

import requests
r = requests.get("some-site.com")
print r.text

我想用袜子代理。但是请求现在仅支持HTTP代理。

我怎样才能做到这一点?

Answers:


114

现代方式:

pip install -U requests[socks]

然后

import requests

resp = requests.get('http://go.to', 
                    proxies=dict(http='socks5://user:pass@host:port',
                                 https='socks5://user:pass@host:port'))

3
当心,当使用SOCKS代理时,重新请求将使用完整URL发出HTTP请求(例如,“ GET example.com HTTP / 1.1”而不是“ GET / HTTP / 1.1”),此行为可能会引起问题。可悲的是,似乎目前没有更好的解决方案。
a3nm 2014年

此外,我找不到在代理设置中使用用户名和密码的方法。不得不求助于urllib2。
包含

9
我正在使用zsh,而我必须这样做,bash -c "pip install -U requests[socks]"否则zsh会抱怨zsh: no matches found: requests[socks]
布鲁斯·孙

3
在Windows上,您还需要:pip install win-inet-
pton

4
@BruceSunpip install 'requests[socks]'就足够了
bakatrouble

53

自2016年4月29日发行的2.10.0requests版本起,支持SOCKS。requests

它需要PySocks,可以与一起安装pip install pysocks

用法示例:

import requests
proxies = {'http': "socks5://myproxy:9191"}
requests.get('http://example.org', proxies=proxies)

3
pip install -U requests[socks] 是enogh
dvska

8
就我而言,仅pip install -U request [socks]不起作用。pip install pysocks是必须的。
DenMark '16

就像对此进行修改一样,要强制将您的版本手动升级requests到支持SOCKS(> 2.10.0)的版本,请运行pip :(pip install requests==2.18.4在撰写本文时为2.18.4),但请检查:pypi。 python.org/pypi/要求提供最新版本(此页面应在顶部标题中显示最新的稳定版本是什么)。
ntk4

我在这个上使用@DenMark。我的工作用笔记本电脑是Mac,无论我尝试什么,请求[袜子]都拒绝为我安装... pysocks神奇地修复了所有问题。
杰里米·洛根

在我的情况下,有socks与模块名称冲突qBittorrent,我需要删除/移动~/.local/share/data/qBittorrent/nova3/socks.py和删除socks.pyc,解决错误信息module 'socks' has no attribute 'create_connection',并bad magic number in 'socks':分别。
水果

41

如果有人尝试了所有这些较早的答案,但仍然遇到诸如以下的问题:

requests.exceptions.ConnectionError: 
   SOCKSHTTPConnectionPool(host='myhost', port=80): 
   Max retries exceeded with url: /my/path 
   (Caused by NewConnectionError('<requests.packages.urllib3.contrib.socks.SOCKSConnection object at 0x106812bd0>: 
   Failed to establish a new connection: 
   [Errno 8] nodename nor servname provided, or not known',))

可能是由于默认情况下requests配置为在连接的本地端解析DNS查询。

尝试将代理URL从更改socks5://proxyhost:1234socks5h://proxyhost:1234。注意额外的内容h(代表主机名解析)。

PySocks软件包模块的默认设置是进行远程解析,我不确定为什么请求使它们的集成变得如此模糊,但是我们到了。


5
那正是我的问题!谢谢!
xbeta

3
这对我来说是确切的问题。它没有通过代理进行DNS查询。当我添加h时,一切正常。
jamescampbell

1
谢谢,该socks5h方法是这样比猴子修补解决方法我很担心我不得不做之前干净多了。
达里安

1
非常好。socks5h://在代理服务器上找不到Python文档的任何地方。一定是在错误的地方找。爱得如此。
Ligemer '18

1
@Ligemer有时,唯一正确的地方是代码。(但是看了代码之后,更新了StackOverflow,现在有两个合适的地方可以看:))
Mahmoud Hashemi

17

您需要安装pysocks,我的版本是1.0,该代码对我有用

import socket
import socks
import requests
ip='localhost' # change your proxy's ip
port = 0000 # change your proxy's port
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, ip, port)
socket.socket = socks.socksocket
url = u'http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=inurl%E8%A2%8B'
print(requests.get(url).text)

大!当我想通过袜子5代理使用软件包(例如flickrapi)时很方便
MZD 16'Jan

2
这不是使用socks代理的好方法,因为它会更改默认套接字并会出错,因此,如果仅进行测试就可以,但不适用于真实情况。
lqhcpsgbl

6

一旦pythonrequests将与SOCKS5pull request合并,它将像使用proxiesdictionary一样简单:

#proxy
        # SOCKS5 proxy for HTTP/HTTPS
        proxies = {
            'http' : "socks5://myproxy:9191",
            'https' : "socks5://myproxy:9191"
        }

        #headers
        headers = {

        }

        url='http://icanhazip.com/'
        res = requests.get(url, headers=headers, proxies=proxies)

请参阅SOCKS代理支持

如果您无法等待request准备就绪且无法使用时requesocks(例如由于缺少pwd内置模块而在GoogleAppEngine上),另一种选择是使用上面提到的PySocks

  1. socks.py从仓库中获取文件,然后将副本放入根文件夹中;
  2. import socksimport socket

urllib2下面的示例中,在与-一起使用之前,请配置并绑定套接字。

import urllib2
import socket
import socks

socks.set_default_proxy(socks.SOCKS5, "myprivateproxy.net",port=9050)
socket.socket = socks.socksocket
res=urllib2.urlopen(url).read()

2
# SOCKS5 proxy for HTTP/HTTPS
proxiesDict = {
    'http' : "socks5://1.2.3.4:1080",
    'https' : "socks5://1.2.3.4:1080"
}

# SOCKS4 proxy for HTTP/HTTPS
proxiesDict = {
    'http' : "socks4://1.2.3.4:1080",
    'https' : "socks4://1.2.3.4:1080"
}

# HTTP proxy for HTTP/HTTPS
proxiesDict = {
    'http' : "1.2.3.4:1080",
    'https' : "1.2.3.4:1080"
}

4
这是最新的Requests版本的工作方式吗?没有requesocks
Gtx

这是proxies最新的requests请求请求的字典,当前尚未被合并。@see-github.com
kennethreitz

1

我在urllib3中安装了pysocks和猴子补丁的create_connection,如下所示:

import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, "127.0.0.1", 1080)

def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                      source_address=None, socket_options=None):
    """Connect to *address* and return the socket object.

    Convenience function.  Connect to *address* (a 2-tuple ``(host,
    port)``) and return the socket object.  Passing the optional
    *timeout* parameter will set the timeout on the socket instance
    before attempting to connect.  If no *timeout* is supplied, the
    global default timeout setting returned by :func:`getdefaulttimeout`
    is used.  If *source_address* is set it must be a tuple of (host, port)
    for the socket to bind as a source address before making the connection.
    An host of '' or port 0 tells the OS to use the default.
    """

    host, port = address
    if host.startswith('['):
        host = host.strip('[]')
    err = None
    for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
        af, socktype, proto, canonname, sa = res
        sock = None
        try:
            sock = socks.socksocket(af, socktype, proto)

            # If provided, set socket level options before connecting.
            # This is the only addition urllib3 makes to this function.
            urllib3.util.connection._set_socket_options(sock, socket_options)

            if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                sock.settimeout(timeout)
            if source_address:
                sock.bind(source_address)
            sock.connect(sa)
            return sock

        except socket.error as e:
            err = e
            if sock is not None:
                sock.close()
                sock = None

    if err is not None:
        raise err

    raise socket.error("getaddrinfo returns an empty list")

# monkeypatch
urllib3.util.connection.create_connection = create_connection


0

我可以在Linux上执行此操作。

$ pip3 install --user 'requests[socks]'
$ https_proxy=socks5://<hostname or ip>:<port> python3 -c \
> 'import requests;print(requests.get("https://httpbin.org/ip").text)'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.