Как заставить запросы python работать через прокси-сервер socks

Я использую замечательную библиотеку Requests в своем скрипте Python:

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

Я хотел бы использовать прокси-сервер socks. Но запросы теперь поддерживают только HTTP-прокси.

Как я могу это сделать?


person lithuak    schedule 26.09.2012    source источник


Ответы (9)


Современный способ:

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'))
person dvska    schedule 27.03.2013
comment
Остерегайтесь: при использовании прокси-сервера SOCKS requesocks будет отправлять HTTP-запросы с полным URL-адресом (например, GET example.com HTTP/ 1.1, а не GET/HTTP/1.1), и такое поведение может вызвать проблемы. К сожалению, кажется, что на данный момент нет лучшего решения. - person a3nm; 07.06.2014
comment
Кроме того, я не нашел способа использовать имя пользователя и пароль в настройках прокси. Пришлось прибегнуть к urllib2. - person Encompass; 22.01.2016
comment
Я использую zsh, и вместо этого я должен сделать bash -c "pip install -U requests[socks]", иначе zsh будет жаловаться zsh: no matches found: requests[socks]. - person Bruce Sun; 12.01.2017
comment
В Windows вам также потребуется: pip install win-inet-pton - person rstaveley; 03.02.2017
comment
@BruceSun pip install 'requests[socks]' будет достаточно - person bakatrouble; 26.01.2019
comment
это действительно изменилось, все, что мне нужно было сделать, это изменить http на https, потому что я использую torsocks на локальной машине - person Ebrahim Karimi; 20.02.2019
comment
Мне нужно было добавить «h» к URL-адресу socks: socks5h://localhost:8080, потому что имя хоста не могло быть разрешено с моей стороны. Из github.com/urllib3/urllib3/issues/1035 кажется, что ' h' сообщает библиотеке, что именно сервер будет разрешать имя хоста. - person Philippe Carphin; 13.08.2020
comment
@PhilippeCarphin socks5h спасает мой день! - person bitdancer; 14.05.2021
comment
pipenv установить 'запросы [socks]' - person anonymous; 25.05.2021

Начиная с requests версии 2.10.0, выпущенной в 2016 – 04-29, requests поддерживает SOCKS.

Для этого требуется PySocks, который можно установить вместе с pip install pysocks.

Пример использования:

import requests
proxies = {'http': "socks5://myproxy:9191"}
requests.get('http://example.org', proxies=proxies)
person Jim    schedule 30.04.2016
comment
pip install -U requests[socks] достаточно - person dvska; 19.05.2016
comment
В моем случае pip install -U requests[socks] сам по себе не работает. pip install pysocks обязателен. - person DenMark; 21.05.2016
comment
В дополнение к этому, чтобы принудительно вручную обновить вашу версию requests до версии, поддерживающей SOCKS (› 2.10.0), запустите pip: pip install requests==2.18.4 (2.18.4 во время пишу это), но проверьте: pypi.python.org/pypi/requests для получения последней версии (на этой странице в верхнем заголовке должна быть указана последняя стабильная версия). - person ntk4; 11.09.2017
comment
Я с @DenMark в этом вопросе. Мой рабочий ноутбук - Mac, и запросы [socks] просто униженно отказывались устанавливать для меня, что бы я ни пытался ... pysocks волшебным образом все исправили. - person Jeremy Logan; 03.05.2019
comment
В моем случае socks имя модуля конфликтует с qBittorrent, мне нужно удалить/переместить ~/.local/share/data/qBittorrent/nova3/socks.py и удалить этот socks.pyc, чтобы устранить сообщение об ошибке module 'socks' has no attribute 'create_connection' и bad magic number in 'socks': соответственно. - person Fruit; 04.08.2019

На случай, если кто-то пробовал все эти старые ответы и все еще сталкивается с такими проблемами, как:

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 (это означает разрешение имени хоста).

Модуль пакета PySocks по умолчанию выполняет удаленное разрешение, и я не уверен, почему запросы сделали их интеграцию это неясно расходящееся, но мы здесь.

person Mahmoud Hashemi    schedule 06.04.2017
comment
Это была именно моя проблема! Спасибо! - person xbeta; 20.11.2017
comment
Это была точная проблема для меня. Он не выполнял DNS-запросы через прокси. Как только я добавил h, все заработало правильно. - person jamescampbell; 30.01.2018
comment
Спасибо, подход socks5h настолько намного чище, чем обходной путь с исправлением обезьяны, который, как я боялся, мне придется использовать раньше. - person Darien; 26.04.2018
comment
Очень хорошо. Я нигде не смог найти socks5h:// документацию Python по прокси. Должно быть, искал не в тех местах. Должен любить ТАК. - person Ligemer; 24.07.2018
comment
@Ligemer иногда единственное правильное место для поиска - это код. (Но посмотрев код, обновите StackOverflow, и теперь есть два правильных места для поиска :) ) - person Mahmoud Hashemi; 24.07.2018
comment
В Ubuntu 19.10, несмотря на переход на socks5h, я все еще получаю эту ошибку: ConnectionError: SOCSHHTTPConnectionPool(host='httpbin.org', port=80): превышено максимальное количество повторных попыток с URL-адресом: /ip (вызвано NewConnectionError('‹urllib3 .contrib.socks.SOCKSConnection объект по адресу 0x7faa6c0512d0›: Не удалось установить новое соединение: [Errno 111] Отказано в соединении')) - person Andrea; 08.07.2020
comment
Я также все еще получаю ошибку SOCSHHTTPConnectionPool. - person Dubstep; 09.11.2020
comment
Спасибо-спасибо-спасибо-ты мой герой! - person lkahtz; 09.02.2021

Вам нужно установить 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)
person lqhcpsgbl    schedule 21.10.2015
comment
Здорово! Это удобно, когда я хочу использовать пакет (например, flickrapi) через socks 5 прокси. - person MZD; 06.01.2016
comment
Это не лучший способ использовать socks-прокси, потому что он изменяет сокет по умолчанию и допустит некоторую ошибку, поэтому, если просто протестировать, все будет в порядке, но не для реальных вещей. - person lqhcpsgbl; 12.06.2016

Как только 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-прокси.

Другой вариант, в случае, если вы не можете дождаться готовности request, когда вы не можете использовать requesocks - как в GoogleAppEngine из-за отсутствия встроенного модуля pwd, это использовать PySocks, упомянутое выше:

  1. Возьмите файл socks.py из репозитория и поместите копию в корневую папку;
  2. Добавьте import socks и import 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()
person loretoparisi    schedule 05.04.2016

Я установил pysocks и пропатчил create_connection в urllib3, вот так:

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
person Edward Betts    schedule 20.02.2016

Я мог бы сделать это в 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)'
person Nizam Mohamed    schedule 20.02.2020

Вы можете просто запустить свой скрипт с переменной окружения 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)'
person Sergey Nemchinov    schedule 06.06.2021

person    schedule
comment
Так это работает в последней версии Requests? Без requesocks? - person Gtx; 17.12.2015
comment
Это proxies словарь для последнего requests запроса на включение, который в это время еще не был объединен. @see — github.com/kennethreitz/requests/pull/2953 - person loretoparisi; 05.04.2016