簡體   English   中英

如何使用請求庫從 http 請求中獲取 IP 地址?

[英]How do I get the IP address from a http request using the requests library?

我正在使用 python 中的請求庫發出 HTTP 請求,但我需要響應 HTTP 請求的服務器的 IP 地址,並且我試圖避免進行兩次調用(並且可能與響應的 IP 地址不同到請求)。

那可能嗎? 是否有任何 python HTTP 庫允許我這樣做?

PS:我還需要發出 HTTPS 請求並使用經過身份驗證的代理。

更新 1:

例子:

import requests

proxies = {
  "http": "http://user:password@10.10.1.10:3128",
  "https": "http://user:password@10.10.1.10:1080",
}

response = requests.get("http://example.org", proxies=proxies)
response.ip # This doesn't exist, this is just an what I would like to do

然后,我想知道響應中的方法或屬性將請求連接到哪些 IP 地址。 在其他庫中,我可以通過查找 sock 對象並使用getpeername()函數來做到這一點。

事實證明,它相當復雜。

這是使用requests版本 1.2.3 時的猴子補丁:

_make_request方法包裝在HTTPConnectionPool以將來自socket.getpeername()的響應存儲在HTTPResponse實例上。

對於我在 python 2.7.3 上,這個實例在response.raw._original_response可用。

from requests.packages.urllib3.connectionpool import HTTPConnectionPool

def _make_request(self,conn,method,url,**kwargs):
    response = self._old_make_request(conn,method,url,**kwargs)
    sock = getattr(conn,'sock',False)
    if sock:
        setattr(response,'peer',sock.getpeername())
    else:
        setattr(response,'peer',None)
    return response

HTTPConnectionPool._old_make_request = HTTPConnectionPool._make_request
HTTPConnectionPool._make_request = _make_request

import requests

r = requests.get('http://www.google.com')
print r.raw._original_response.peer

產量:

('2a00:1450:4009:809::1017', 80, 0, 0)

啊,如果涉及代理或響應分塊,則不會調用HTTPConnectionPool._make_request

所以這里有一個新版本修補httplib.getresponse

import httplib

def getresponse(self,*args,**kwargs):
    response = self._old_getresponse(*args,**kwargs)
    if self.sock:
        response.peer = self.sock.getpeername()
    else:
        response.peer = None
    return response


httplib.HTTPConnection._old_getresponse = httplib.HTTPConnection.getresponse
httplib.HTTPConnection.getresponse = getresponse

import requests

def check_peer(resp):
    orig_resp = resp.raw._original_response
    if hasattr(orig_resp,'peer'):
        return getattr(orig_resp,'peer')

跑步:

>>> r1 = requests.get('http://www.google.com')
>>> check_peer(r1)
('2a00:1450:4009:808::101f', 80, 0, 0)
>>> r2 = requests.get('https://www.google.com')
>>> check_peer(r2)
('2a00:1450:4009:808::101f', 443, 0, 0)
>>> r3 = requests.get('http://wheezyweb.readthedocs.org/en/latest/tutorial.html#what-you-ll-build')
>>> check_peer(r3)
('162.209.99.68', 80)

還檢查了在設置代理的情況下運行; 返回代理地址。


更新2016/01/19

est提供了一種不需要猴子補丁的替代方案

rsp = requests.get('http://google.com', stream=True)
# grab the IP while you can, before you consume the body!!!!!!!!
print rsp.raw._fp.fp._sock.getpeername()
# consume the body, which calls the read(), after that fileno is no longer available.
print rsp.content  

更新2016/05/19

從評論中復制到此處以獲得可見性, Richard Kenneth Niescior提供了以下已確認可用於請求 2.10.0 和 Python 3 的內容。

rsp=requests.get(..., stream=True)
rsp.raw._connection.sock.getpeername()

更新2019/02/22

帶有請求版本 2.19.1 的 Python3。

resp=requests.get(..., stream=True)
resp.raw._connection.sock.socket.getsockname()

更新2020/01/31

帶有請求 2.22.0 的 Python3.8

resp = requests.get('https://www.google.com', stream=True)
resp.raw._connection.sock.getsockname()

嘗試:

import requests

proxies = {
  "http": "http://user:password@10.10.1.10:3128",
  "https": "http://user:password@10.10.1.10:1080",
}

response = requests.get('http://jsonip.com', proxies=proxies)
ip = response.json()['ip']
print('Your public IP is:', ip)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM