Как получить IP-адрес из http-запроса с помощью библиотеки запросов?

Я делаю HTTP-запросы, используя библиотеку запросов в python, но мне нужен ip-адрес с сервера, который ответил на http-запрос, и я пытаюсь избежать двух вызовов (и, возможно, с другим ip-адресом от того, который ответил на запрос.

это возможно? Позволяет ли мне это сделать любая http-библиотека python?

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 ().

1 ответов


оказывается, что это довольно сложно.

вот обезьяна-патч при использовании requests версия 1.2.3:

упаковка _make_request метод on 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 предложения альтернатива, которая не нуждается в monkey-patch:

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

от комментарии, копирование здесь для наглядности,Ричард Кеннет Niescior предлагает следующее, что подтверждается работой с запросами 2.10.0 и Python 3.

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