获取python requests模块请求的ip地址

事情的起因是这样的:
开发了一个探针监控CDN供应商的节点质量,使用的requests模块每隔一段时间请求CDN数据,当请求失败的时候进行报警,由于CDN在不同时刻不同地理位置请求域名分配的节点ip不同所以就要求拿到当时请求到的地址,代码如下

想要拿到requests的请求地址需要访问偏底层的数据结构文档如是说:In the rare case that you’d like to get the raw socket response from the server, you can access
r.raw. If you want to do this, make sure you set stream=True in your initial request. Once you do, you can do this

1
2
3
4
import requests
a = requests.get('url',stream = True)
ip_and_port = a.raw._connection.sock.getpeername()
#('ip',port)

其实到这里不是重点,重点是在使用过程中,如果在调用a.raw._connection.sock.getpeername()之前进行了例如a.text的调用那么这时候就会报错:a.raw._connection.sock.getpeername()!!!当时就特别好奇,这调用关系不同怎么还这样了,于是接着看文档,找到如下部分:

import requests
r = requests.get(‘https://api.github.com/events‘)
r.text u’[{“repository”:{“open_issues”:0,”url”:”https://github.com/
Requests will automatically decode content from the server. Most unicode charsets are seamlessly decoded.
When you make a request, Requests makes educated guesses about the encoding of the response based on the HTTP headers. The text encoding guessed by Requests is used when you access r.text. You can find out what encoding Requests is using, and change it, using the r.encoding property:
print r.encoding
‘utf-8’
r.encoding = ‘ISO-8859-1’
If you change the encoding, Requests will use the new value of r.encoding whenever you call r.text. You might want to do this in any situation where you can apply special logic to work out what the encoding of the content will be. For example, HTTP and XML have the ability to specify their encoding in their body. In situations like this, you should use r.content to find the encoding, and then set r.encoding. This will let you use r.text with the correct encoding.

可以看到的是在调用r.text的时候其实内部是有处理的,包括encoding,联系当时的报错信息,可以得出的结论就是当访问r.text之后关闭了底层的sock链接,因此会爆出raw is None的错误:)