如何从Requests的HEAD请求中捕获目标IP和端口?
解决requests HEAD请求捕获目标IP和端口的问题
嘿,刚好碰到过类似的需求,我来给你几个靠谱的解决办法,顺便澄清你之前的误解~
先说说你遇到的问题
你之前尝试的r.raw._original_response.peer无效,大概率是因为HEAD请求默认会在获取响应头后立即关闭连接,导致底层的原始响应对象已经被释放,拿不到有效数据。另外你担心stream=True会让timeout失效,其实这是个误解——timeout参数依然会生效,它控制的是连接超时和读取超时,哪怕开启了stream,只要在规定时间内没建立连接或拿到响应头,就会触发超时。
方案1:用stream=True配合socket获取IP和端口
这是最直接的办法,开启stream后连接不会立即关闭,我们可以从底层socket里拿到目标的IP和端口:
import requests # 替换成你的实际配置 headers = {"User-Agent": "Mozilla/5.0"} finalURL = "example.com" timeout = 5 try: # 开启stream=True,同时保留timeout设置 r = requests.head( url='http://' + finalURL, headers=headers, timeout=timeout, allow_redirects=True, stream=True ) # 从socket获取目标IP和端口 target_ip_port = r.raw._connection.sock.getpeername() print('目标IP和端口:', target_ip_port) # 输出你原本需要的信息 print('Status', r.status_code) print('Headers', r.headers) print('Elapsed Total', r.elapsed.total_seconds()) # 记得手动关闭连接,避免资源泄漏 r.close() except Exception as e: print(f"请求出错: {str(e)}")
方案2:自定义HTTPAdapter(无需stream=True)
如果你不想开启stream,可以通过自定义Adapter来捕获连接信息,这种方式更优雅,适合在Session级别统一处理:
import requests from requests.adapters import HTTPAdapter class IPTrackingAdapter(HTTPAdapter): def build_response(self, req, resp): # 从连接池的socket中捕获IP和端口 target_ip_port = resp._pool.sock.getpeername() print(f"捕获到目标IP和端口: {target_ip_port}") # 调用父类方法继续构建响应 return super().build_response(req, resp) # 初始化会话并挂载自定义Adapter session = requests.Session() session.mount('http://', IPTrackingAdapter()) # 替换成你的实际配置 headers = {"User-Agent": "Mozilla/5.0"} finalURL = "example.com" timeout = 5 try: r = session.head( url='http://' + finalURL, headers=headers, timeout=timeout, allow_redirects=True ) print('Status', r.status_code) print('Headers', r.headers) print('Elapsed Total', r.elapsed.total_seconds()) except Exception as e: print(f"请求出错: {str(e)}")
额外提醒
如果你的allow_redirects=True,捕获到的是最终重定向目标的IP和端口。如果想获取初始请求的目标IP,可以把allow_redirects=False,或者在Adapter里处理每个重定向步骤。
内容的提问来源于stack exchange,提问作者Nkk
相关产品推荐
相关产品推荐

