如何使用请求库从http请求中获取IP地址? [英] How do I get the IP address from a http request using the requests library?

查看:442
本文介绍了如何使用请求库从http请求中获取IP地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用python中的请求库发出HTTP请求,但我需要来自响应HTTP请求的服务器的IP地址,因此我试图避免进行两次调用(并且可能与IP地址有不同的IP地址)响应请求的人.

I am making HTTP requests using the requests library in python, but I need the ip address from the server that responded the http request and I'm trying to avoid to make two calls (and possibly having a different ip address from the one that responded the request.

有可能吗?是否有任何python http库允许我这样做?

Is that possible? Does any python http library allows me to do that?

ps:我还需要发出HTTPS请求并使用经过身份验证的代理.

ps: I also need to make HTTPS requests and to use an authenticated proxy.

更新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()方法来做到这一点.

then, I would like to know to which IP address requests connected from a method or property in the response. In other libraries I was able to do that by finding the sock object and using the getpeername() method.

推荐答案

事实证明,它确实涉及其中.

It turns out that it's rather involved.

在使用requests 1.2.3版时,这是一个猴子补丁:

Here's a monkey-patch while using requests version 1.2.3:

HTTPConnectionPool上包装_make_request方法,将socket.getpeername()的响应存储在HTTPResponse实例上.

Wrapping the _make_request method on HTTPConnectionPool to store the response from socket.getpeername() on the HTTPResponse instance.

对于我来说,在python 2.7.3上,该实例在response.raw._original_response上可用.

For me on python 2.7.3, this instance was available on 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的新版本:

So here's a new version patching httplib.getresponse instead:

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)

还检查了已设置代理的运行情况;返回代理地址.

Also checked running with proxies set; proxy address is returned.

更新 2016/01/19

Update 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


Update 2016/05/19

从评论中复制到此处以提高可见性, Richard Kenneth Niescior 提供以下已确认有效的内容请求2.10.0和Python 3.

From the comments, copying here for visibility, Richard Kenneth Niescior offers the following that is confirmed working with requests 2.10.0 and Python 3.

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


更新 2019/02/22


Update 2019/02/22

请求版本为2.19.1的Python3.

Python3 with requests version 2.19.1.

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


更新 2020/01/31


Update 2020/01/31

带有请求2.22.0的Python3.8

Python3.8 with requests 2.22.0

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

这篇关于如何使用请求库从http请求中获取IP地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆