Cómo hacer que las solicitudes de Python funcionen a través de socks proxy


81

Estoy usando la gran biblioteca de solicitudes en mi secuencia de comandos de Python:

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

Me gustaría usar socks proxy. Pero las solicitudes solo son compatibles con el proxy HTTP ahora.

¿Cómo puedo hacer eso?

Respuestas:


114

La forma moderna:

pip install -U requests[socks]

entonces

import requests

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

3
Tenga cuidado, al usar un proxy SOCKS, los requesocks harán solicitudes HTTP con la URL completa (por ejemplo, "GET example.com HTTP / 1.1" en lugar de "GET / HTTP / 1.1") y este comportamiento puede causar problemas. Lamentablemente, parece que no hay una mejor solución disponible por ahora.
— a3nm

Además, no he encontrado ninguna forma de utilizar el nombre de usuario y la contraseña en la configuración del proxy. Tuve que recurrir a urllib2.
— Encompass

9
Estoy usando zsh y tengo que hacerlo, de lo bash -c "pip install -U requests[socks]"contrario, zsh se quejará zsh: no matches found: requests[socks].
— Bruce Sun

3
En Windows también necesita: pip install win-inet-pton
— rstaveley

4
@BruceSun pip install 'requests[socks]'sería suficiente
— bakatrouble

53

A partir de la requestsversión 2.10.0 , publicada el 29 de abril de 2016, es requestscompatible con SOCKS.

Requiere PySocks , que se puede instalar con pip install pysocks.

Uso de ejemplo:

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

3
pip install -U requests[socks] is enogh
— dvska

8
En mi caso, las solicitudes pip install -U [calcetines] por sí solas no funcionan. pip install pysocks es imprescindible.
— DenMark

Al igual que enmendar esto, para forzar una actualización manual de su versión de requestsa una versión que admita SOCKS (> 2.10.0), ejecute pip: pip install requests==2.18.4(2.18.4 en el momento de escribir esto), pero verifique: pypi. python.org/pypi/requests para la última versión (esta página debería mostrarle en el encabezado superior cuál es la última versión estable).
— ntk4

Estoy con @DenMark en este. Mi computadora portátil de trabajo es una Mac y las solicitudes [socks] simplemente se negaron abyectamente a instalarme sin importar lo que intenté ... pysocks lo arregló todo mágicamente.
— Jeremy Logan

En mi caso, hay un socksconflicto con el nombre del módulo qBittorrent, necesito eliminar / mover ~/.local/share/data/qBittorrent/nova3/socks.pyy eliminar eso socks.pyc, para resolver el mensaje de error module 'socks' has no attribute 'create_connection'y bad magic number in 'socks':respectivamente.
— Fruta

42

En caso de que alguien haya probado todas estas respuestas anteriores y todavía tenga problemas como:

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

Puede deberse a que, de forma predeterminada, requestsestá configurado para resolver consultas de DNS en el lado local de la conexión.

Intente cambiar la URL de su proxy de socks5://proxyhost:1234a socks5h://proxyhost:1234. Tenga en cuenta el extra h(significa resolución de nombre de host).

El módulo de paquete de PySocks predeterminado es hacer resolución remota , y no estoy seguro de por qué las solicitudes hicieron que su integración fuera tan oscuramente divergente, pero aquí estamos.


6
¡Ese era exactamente mi problema! ¡Gracias!
— xbeta

4
Este fue el problema exacto para mí. No estaba haciendo consultas de DNS a través del proxy. Tan pronto como agregué la h, todo funcionó correctamente.
— jamescampbell

1
Gracias, el socks5henfoque es así mucho más limpia que la solución mono-parches que estaba preocupado que tendría que hacer antes.
— Darien

1
Muy agradable. No pude encontrar socks5h://ningún lugar para la documentación de Python en proxies. Debe haber estado buscando en los lugares equivocados. Tengo que amar TAN.
— Ligemer

1
@Ligemer a veces, el único lugar correcto para buscar es el código. (Pero después de mirar el código, actualice StackOverflow, y ahora hay dos lugares correctos para buscar :))
— Mahmoud Hashemi

17

Necesitas instalar pysocks , mi versión es 1.0 y el código funciona para mí:

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)

¡Excelente! Es conveniente cuando quiero usar un paquete (por ejemplo, flickrapi) a través del proxy socks 5
— MZD

2
No es una buena manera de usar socks proxy, porque cambia el socket predeterminado y cometerá algún error, por lo que si solo lo prueba, estará bien, pero no para cosas reales.
— lqhcpsgbl

6

Tan pronto como Python requestsse combine con la SOCKS5solicitud de extracción, será tan simple como usar el proxiesdiccionario:

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

Ver soporte de proxy SOCKS

Otra opción, en caso de que no pueda esperar requesta estar listo, cuando no pueda usar requesocks, como en GoogleAppEngine debido a la falta de pwdun módulo incorporado, es usar PySocks que se mencionó anteriormente:

  1. Tome el socks.pyarchivo del repositorio y coloque una copia en su carpeta raíz;
  2. Agregar import socksyimport socket

En este punto, configure y vincule el socket antes de usar con urllib2- en el siguiente ejemplo:

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
¿Es así como funciona en la última versión de Requests? Sin requesocks?
— Gtx

Este es el proxiesdiccionario de la última requestssolicitud de extracción, que en este momento aún no se ha fusionado. @see - github.com/kennethreitz/requests/pull/2953
— loretoparisi

1

Instalé pysocks y mono parcheado create_connection en urllib3, así:

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

Podría hacer esto en 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)'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.