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?

Lithuak
fuente

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'))
dvska
fuente
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)
Jim
fuente
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.

Mahmoud Hashemi
fuente
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)
lqhcpsgbl
fuente
¡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()
Loretoparisi
fuente
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"
}
wcc526
fuente
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
Edward Betts
fuente
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)'
Nizam Mohamed
fuente