我们已经学会了通过requests.get()或者requests.post()实现发送请求。看起来很简单,是不是,也很好用。但是你知道requests底层是如何实现的吗。还有,我们有时候需要定义一些我们自己特定情况下的请求。为了解决这个问题,你需要遇到requests的文档中高级的部分。
1.文档位置
浏览器打开http://cn.python-requests.org/zh_CN/latest/user/advanced.html
你需要阅读下 “会话对象”,“准备的请求”,“请求和响应”这些内容,需要了解这个特点:
会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookie,期间使用urllib3
的 connection pooling功能。所以如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而带来显著的性能提升。
这有一个好处,大大节约了性能。因为,每次发送HTTP请求,tcp连接都需要经过三次握手。如果我们每个请求都需要连接一次,握手三次,然后断开。那么这个测试大量接口用例的时候,就会变得很慢很慢,效率很低。
2. Session发送请求,底层实现原理
在一个Session对象下,session负责代理,超时和一些验证的设置。然后我们把请求的body,headers ,auth封装在一个PreparedRequest对象里,通过session对象,执行send()方法,把准备请求对象给发送出去,这样我们就得到了相应对象,一个response主要有text和json方法。也就是显示相应主体内容的根据不同格式去显示或者打印出来。
3. 根据这个原理,举例一个自定义请求
import json
import requests
from requests import exceptions
URL = 'https://api.github.com'
def build_uri(endpoint):
return '/'.join([URL, endpoint])
def better_output(json_str):
return json.dumps(json.loads(json_str), indent=4)
def custom_request():
from requests import Request, Session
s = Session() # 初始化一个session
headers = {'User-Agent':'fake1.3.4'} # fake是伪装的意思,就是设置一个假的
request = Request('GET', build_uri('user/emails'), auth=('xxxxx','xxxxxx'), headers=headers)
prepped = request.prepare() #初始化一个prepare对象,用来包装请求的headers和body
print(prepped.body) # 打印出来应该是空,毕竟目前还没有发送请求
print(prepped.headers)
response = s.send(prepped, timeout=5) # 通过session对象调用发送请求,内容是prepped包装好的请求
print(response.status_code)
print(response.headers)
print(response.text)
if __name__ == '__main__':
custom_request()
运行结果
None
{'User-Agent': 'fake1.3.4', 'Authorization': 'Basic QW50aG9ueWxpdTg2OmNhJGhjMHdB'}
200
{'Date': 'Tue, 29 Aug 2017 08:44:55 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': '84', 'Server': 'GitHub.com',
'Status': '200 OK', 'X-RateLimit-Limit': '5000', 'X-RateLimit-Remaining': '4999', 'X-RateLimit-Reset': '1503999895',
'Cache-Control': 'private, max-age=60, s-maxage=60', 'Vary': 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding',
'ETag': '"64093aa6319014f3e0a3d4b785fce6dd"', 'X-GitHub-Media-Type': 'github.v3; format=json', 'Access-Control-Expose-Headers': 'ETag,
Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval',
'Access-Control-Allow-Origin': '*', 'Content-Security-Policy': "default-src 'none'", 'Strict-Transport-Security': 'max-age=31536000;
includeSubdomains; preload', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'deny', 'X-XSS-Protection': '1; mode=block',
'X-Runtime-rack': '0.060934', 'X-GitHub-Request-Id': '0FC7:2E7F1:92D36D:BBA2E7:59A52986'}
[{"email":"[email protected]","primary":true,"verified":true,"visibility":"public"}]
结果分析:
一开始输出body内容是空,因为我们只是准备了一个请求,还没有执行发送,可能没有响应内容。200表示请求成功,后面输出了响应头部信息和响应的text内容。