web-dev-qa-db-ja.com

リクエストライブラリを使用してhttpリクエストからIPアドレスを取得するにはどうすればよいですか?

Pythonのリクエストライブラリを使用してHTTPリクエストを作成していますが、httpリクエストに応答したサーバーからのIPアドレスが必要です。リクエスト。

それは可能ですか? python httpライブラリはそれを可能にしますか?

ps:HTTPSリクエストを作成し、認証されたプロキシを使用する必要もあります。

更新1:

例:

import requests

proxies = {
  "http": "http://user:[email protected]:3128",
  "https": "http://user:[email protected]: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()メソッドを使用することでそれを行うことができました。

22
gawry

それはむしろ関与していることがわかります。

requestsバージョン1.2.3を使用しているときのサルパッチは次のとおりです。

HTTPConnectionPoolの__make_request_メソッドをラップして、HTTPResponseインスタンスのsocket.getpeername()からの応答を保存します。

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

コメントから、ここにコピーして表示します 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()
_
37
MattH