Як змусити запити python працювати через проксі-сервер socks


83

Я використовую чудову бібліотеку запитів у своєму сценарії Python:

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

Я хотів би використовувати проксі-сервер для шкарпеток. Але Запити зараз підтримують лише проксі HTTP.

Як я можу це зробити?

Відповіді:


116

Сучасний спосіб:

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 запити HTTP будуть зроблені із повною URL-адресою (наприклад, "GET example.com HTTP / 1.1", а не "GET / HTTP / 1.1"), і ця поведінка може спричинити проблеми. На жаль, здається, що зараз немає кращого рішення.
a3nm

Крім того, я не знайшов способу використовувати ім'я користувача та пароль у налаштуваннях проксі. Довелося вдаватися до urllib2.
Охопіть

9
Я використовую zsh, і bash -c "pip install -U requests[socks]"замість цього я повинен це зробити, інакше zsh скаржиться zsh: no matches found: requests[socks].
Bruce Sun

3
У Windows вам також потрібно: pip install win-inet-pton
rstaveley

4
@BruceSun pip install 'requests[socks]'було б достатньо
bakatrouble

55

Станом на requestsверсію 2.10.0 , випущену 29.04.2016, requestsпідтримує SOCKS.

Для цього потрібен PySocks , який можна встановити за допомогою pip install pysocks.

Приклад використання:

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

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

8
Як на мій випадок, лише запити на встановлення -U [socks] не працюють. pip встановити pysocks - це обов’язково.
DenMark

Так само, як внести зміни до цього, щоб змусити вручну оновити вашу версію requestsдо версії, яка підтримує SOCKS (> 2.10.0), запустіть pip: pip install requests==2.18.4(2.18.4 на момент написання цього), але перевірте: pypi. python.org/pypi/requests для останньої версії (ця сторінка повинна показати вам у верхньому заголовку, що таке остання стабільна версія).
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':відповідно.
Фрукти

43

Якщо хтось спробував усі ці старіші відповіді і все ще стикається з такими проблемами:

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 має робити віддалене роздільну здатність , і я не впевнений, чому запити зробили свою інтеграцію такою неясно різною, але ми тут.


6
Це було саме моє питання! Дякую!
xbeta

4
Це було саме для мене питання. Він не робив запити DNS через проксі. Як тільки я додав h, все працювало належним чином.
jamescampbell

1
Спасибі, socks5hпідхід так набагато чистіше , ніж мавпа-латання обхідного я хвилювався , я мав би зробити раніше.
Дарієн

1
Дуже мило. Я socks5h://ніде не міг знайти документацію Python про проксі. Мабуть, шукали не там, де. Повинен любити ТАК.
Лігемер,

1
@Ligemer іноді єдиним правильним місцем для пошуку є код. (Але, подивившись код, оновіть StackOverflow, і тепер є два потрібні місця, на які можна подивитися :))
Махмуд Хашемі

18

Вам потрібно встановити 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)

Чудово! Це зручно, коли я хочу використовувати пакет (наприклад, flickrapi) через проксі-сервер nocks 5
MZD

2
Це невдалий спосіб використовувати проксі-сервер socks, оскільки він змінює сокет за замовчуванням і припуститься помилки, тому, якщо просто перевірити, це буде нормально, але не для реальних речей.
lqhcpsgbl

6

Як тільки 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()

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
Це так працює в останній версії запитів? Без requesocks?
Gtx

Це proxiesсловник останнього requestsзапиту на витяг, який на цей час ще не був об’єднаний. @see - github.com/kennethreitz/requests/pull/2953
loretoparisi

2

Я встановив 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

0

Можливо, це може допомогти:

https://github.com/kennethreitz/requests/pull/478


2
Дискусійний потік, здається, показує, що вони хочуть інтегрувати підтримку SOCKS в urllib3, а потім запити. На сьогоднішній день github.com/shazow/urllib3/pull/68 все ще відкритий.
David Xia

питання github.com/shazow/urllib3/pull/68 зараз закрито (але я не перевіряв, чи працює воно насправді).
Ян Влчинський,

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)'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.