【问题标题】:How to make python Requests work via socks proxy如何通过 socks 代理使 python 请求工作
【发布时间】:2012-09-18 01:18:39
【问题描述】:

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

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

我想使用 socks 代理。但是 Requests 现在只支持 HTTP 代理。

我该怎么做?

【问题讨论】:

    标签: python proxy socks python-requests


    【解决方案1】:

    现代方式:

    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'))
    

    【讨论】:

    • 当心,当使用 SOCKS 代理时,requesocks 将使用完整的 URL 发出 HTTP 请求(例如,“GET example.com HTTP/1.1”而不是“GET / HTTP/1.1”),并且这种行为可能造成问题。可悲的是,目前似乎没有更好的解决方案。
    • 我正在使用 zsh,我必须这样做 bash -c "pip install -U requests[socks]" 否则 zsh 会抱怨 zsh: no matches found: requests[socks]
    • 在 Windows 上你还需要:pip install win-inet-pton
    • @BruceSun pip install 'requests[socks]' 就足够了
    • 我需要在 socks URL 中添加一个“h”:socks5h://localhost:8080,因为我无法解析主机名。从github.com/urllib3/urllib3/issues/1035 看来,'h' 告诉库服务器将是解析主机名的服务器。
    【解决方案2】:

    截至 2016 年 4 月 29 日发布的 requests 版本 2.10.0requests 支持 SOCKS。

    需要PySocks,可以用pip install pysocks安装。

    示例用法:

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

    【讨论】:

    • pip install -U requests[socks] 够了
    • 就我而言, pip install -U requests[socks] 单独不起作用。 pip install pysocks 是必须的。
    • 就像对此进行修改,即强制将您的 requests 版本手动升级到支持 SOCKS (> 2.10.0) 的版本,运行 pip :pip install requests==2.18.4(撰写本文时为 2.18.4),但请检查:pypi.python.org/pypi/requests 以获得最新版本(此页面应在顶部标题中向您显示最新的稳定版本是什么)。
    • 我和@DenMark 一起讨论这个问题。我的工作笔记本电脑是 Mac,无论我尝试什么,请求 [socks] 都拒绝为我安装...... pysocks 神奇地修复了一切。
    • 在我的情况下,socks 模块名称与 qBittorrent 冲突,我需要删除/移动 ~/.local/share/data/qBittorrent/nova3/socks.py 并删除 socks.pyc,以解决错误消息 module 'socks' has no attribute 'create_connection'bad magic number in 'socks':分别。
    【解决方案3】:

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

    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:1234 更改为 socks5h://proxyhost:1234。注意额外的h(它代表主机名解析)。

    The PySocks package module default is to do remote resolution,我不知道为什么请求使their integration 如此模糊地分歧,但我们来了。

    【讨论】:

    • 这正是我的问题!谢谢!
    • 这正是我的问题。它没有通过代理进行 DNS 查询。一旦我添加了 h,一切正常。
    • 谢谢,socks5h 方法如此比我之前担心必须做的猴子修补解决方法干净得多。
    • 非常好。我在任何地方都找不到socks5h:// 以获取有关代理的 Python 文档。一定是找错地方了。一定很喜欢。
    • @Ligemer 有时唯一合适的地方就是代码。 (但是查看了代码,更新了 StackOverflow,现在有两个正确的地方可以查看 :))
    【解决方案4】:

    您需要安装 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)
    

    【讨论】:

    • 太棒了!当我想通过 socks 5 代理使用包(例如 flickrapi)时很方便
    • 使用socks代理不是一个好办法,因为它改变了默认的socket,会出错,所以如果只是测试就可以了,但不是真的。
    【解决方案5】:

    一旦 python requests 将与 SOCKS5 合并请求,它将像使用 proxies 字典一样简单:

    #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 Proxy Support

    另一个选项,如果你不能等待request 准备好,当你不能使用requesocks - 比如在GoogleAppEngine 上由于缺少pwd 内置模块,是使用PySocks 那上面提到过:

    1. 从 repo 中获取 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()
    

    【讨论】:

      【解决方案6】:

      您可以使用 https_proxy 环境变量运行您的脚本。

      1. 如有必要,安装 socks 支持。
      pip install PySocks
      pip install pysocks5
      
      1. 设置环境变量
      export https_proxy=socks5://<hostname or ip>:<port>
      
      1. 运行您的脚本。此示例使用代理发出请求并显示 IP 地址:
      echo Your real IP
      python -c 'import requests;print(requests.get("http://ipinfo.io/ip").text)'
      
      echo IP with socks-proxy
      python -c 'import requests;print(requests.get("https://ipinfo.io/ip").text)'
      

      【讨论】:

        【解决方案7】:
        # 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"
        }
        

        【讨论】:

        【解决方案8】:

        我在 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
        

        【讨论】:

          【解决方案9】:

          我可以在 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)'
          

          【讨论】:

            猜你喜欢
            • 2012-06-13
            • 1970-01-01
            • 1970-01-01
            • 2013-08-28
            • 2021-03-07
            • 1970-01-01
            • 2014-04-29
            • 2023-04-06
            • 1970-01-01
            相关资源
            最近更新 更多