Cách làm cho Yêu cầu python hoạt động thông qua proxy vớ


81

Tôi đang sử dụng thư viện Yêu cầu tuyệt vời trong tập lệnh Python của mình:

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

Tôi muốn sử dụng proxy vớ. Nhưng yêu cầu hiện chỉ hỗ trợ proxy HTTP.

Làm thế nào tôi có thể làm điều đó?

Câu trả lời:


114

Cách hiện đại:

pip install -U requests[socks]

sau đó

import requests

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

3
Lưu ý, khi sử dụng proxy SOCKS các yêu cầu sẽ tạo ra các yêu cầu HTTP với URL đầy đủ (ví dụ: "GET example.com HTTP / 1.1" thay vì "GET / HTTP / 1.1") và hành vi này có thể gây ra sự cố. Đáng buồn thay, có vẻ như không có giải pháp nào tốt hơn cho bây giờ.
a3nm

Ngoài ra, tôi không tìm thấy cách nào để sử dụng tên người dùng và mật khẩu trong cài đặt proxy. Đã phải dùng đến urllib2.
Bao gồm

9
Tôi đang sử dụng zsh và tôi phải làm bash -c "pip install -U requests[socks]"thay thế nếu không zsh sẽ phàn nàn zsh: no matches found: requests[socks].
Bruce Sun

3
Trên Windows bạn cũng cần: pip cài đặt win-inet-pton
rstaveley

4
@BruceSun pip install 'requests[socks]'sẽ là đủ
bakatrouble

53

Kể từ requestsphiên bản 2.10.0 , phát hành vào ngày 2016-04-29, requestshỗ trợ SOCKS.

Nó yêu cầu PySocks , có thể được cài đặt bằng pip install pysocks.

Ví dụ sử dụng:

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

3
pip install -U requests[socks] là enogh
dvska

8
Đối với trường hợp của tôi, chỉ riêng yêu cầu pip install -U [vớ] không hoạt động. pip cài đặt pysocks là phải.
DenMark

Cũng giống như để sửa đổi điều này, điều đó để buộc nâng cấp thủ công phiên bản của bạn requestslên phiên bản hỗ trợ SOCKS (> 2.10.0), hãy chạy pip: pip install requests==2.18.4(2.18.4 tại thời điểm viết bài này), nhưng hãy kiểm tra: pypi. python.org/pypi/requests cho phiên bản mới nhất (trang này sẽ hiển thị cho bạn ở tiêu đề trên cùng phiên bản ổn định mới nhất là gì).
ntk4

Tôi với @DenMark về vấn đề này. Máy tính xách tay làm việc của tôi là máy Mac và yêu cầu [tất] chỉ bị từ chối cài đặt cho tôi bất kể tôi đã thử gì ... pysocks đã sửa mọi thứ một cách kỳ diệu.
Jeremy Logan

Trong trường hợp của tôi, có socksxung đột tên mô-đun với qBittorrent, tôi cần xóa / di chuyển ~/.local/share/data/qBittorrent/nova3/socks.pyvà loại bỏ điều đó socks.pyc, để giải quyết thông báo lỗi module 'socks' has no attribute 'create_connection'bad magic number in 'socks':tương ứng.
Trái cây

42

Trong trường hợp ai đó đã thử tất cả các câu trả lời cũ hơn này và vẫn gặp sự cố như:

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

Có thể do, theo mặc định, requestsđược định cấu hình để giải quyết các truy vấn DNS ở phía cục bộ của kết nối.

Hãy thử thay đổi URL proxy của bạn từ socks5://proxyhost:1234thành socks5h://proxyhost:1234. Lưu ý thêm h(nó là viết tắt của độ phân giải tên máy chủ).

Mặc định của mô-đun gói PySocks là thực hiện giải quyết từ xa và tôi không chắc tại sao các yêu cầu lại thực hiện tích hợp của chúng hoàn toàn khác nhau, nhưng chúng tôi ở đây.


6
Đó chính xác là vấn đề của tôi! Cảm ơn!
xbeta

4
Đây là vấn đề chính xác đối với tôi. Nó không thực hiện các truy vấn DNS thông qua proxy. Ngay sau khi tôi thêm chữ h, mọi thứ hoạt động bình thường.
jamescampbell

1
Cảm ơn, các socks5hcách tiếp cận là rất nhiều bụi hơn workaround khỉ vá Tôi đã lo lắng tôi sẽ phải làm trước.
Darien

1
Rất đẹp. Tôi không thể tìm thấy socks5h://tài liệu Python về proxy ở bất kỳ đâu. Chắc là đã nhìn nhầm chỗ. Gotta tình yêu SO.
Ligemer

1
@Ligemer đôi khi nơi thích hợp duy nhất để xem là mã. (Tuy nhiên, khi nhìn vào mã, cập nhật StackOverflow, và hiện nay có hai nơi quyền xem xét :))
Mahmoud Hashemi

17

Bạn cần cài đặt pysocks , phiên bản của tôi là 1.0 và mã phù hợp với tôi:

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)

Tuyệt quá! Đó là thuận lợi khi tôi muốn sử dụng một gói phần mềm (ví dụ flickrapi) thông qua vớ 5 proxy
MZD

2
Đó không phải là một cách tốt để sử dụng vớ proxy, vì nó thay đổi socket mặc định và sẽ mắc một số lỗi, vì vậy nếu chỉ cần kiểm tra thì sẽ ổn, nhưng không phải đối với những thứ thực.
lqhcpsgbl

6

Ngay sau khi python requestssẽ được hợp nhất với SOCKS5pull request, nó sẽ thực hiện đơn giản như sử dụng proxiestừ điển:

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

Xem Hỗ trợ proxy của SOCKS

Một tùy chọn khác, trong trường hợp bạn không thể chờ requestsẵn sàng, khi bạn không thể sử dụng requesocks- như trên GoogleAppEngine do thiếu pwdmô-đun tích hợp, là sử dụng PySocks đã được đề cập ở trên:

  1. Lấy socks.pytệp từ repo và đặt một bản sao vào thư mục gốc của bạn;
  2. Thêm import socksimport socket

Tại thời điểm này, hãy cấu hình và liên kết socket trước khi sử dụng với urllib2- trong ví dụ sau:

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
Đây có phải là cách nó hoạt động trong phiên bản Yêu cầu mới nhất không? Không có requesocks?
Gtx 17/12/15

Đây là proxiestừ điển cho requestsyêu cầu kéo mới nhất , mà tại thời điểm này chưa được hợp nhất. @see - github.com/kennethreitz/requests/pull/2953
loretoparisi

1

Tôi đã cài đặt pysocks và con khỉ đã vá create_connection trong urllib3, như thế này:

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

Tôi có thể làm điều này trên 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)'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.