深入理解Requests库中的请求与响应模型
前言
在Python的网络请求库中,Requests库以其简洁优雅的API设计赢得了广大开发者的青睐。本文将深入剖析Requests库的核心组成部分——请求与响应模型,帮助开发者更好地理解和使用这个强大的工具。
请求与响应模型的基本概念
为什么需要模型?
想象一下在餐厅点餐的过程:你不会只是简单地说"我要食物",而是会提供具体的细节——"一份大号意大利辣香肠披萨,送到主街123号"。餐厅会根据这些信息准备食物,并在送达时附带收据。
网络请求同样遵循这样的模式。你需要明确告诉服务器:
- 你想要什么(URL路径,如
/get或post) - 如何交互(请求方法,如GET或POST)
- 额外的细节(如请求头或发送的数据)
服务器则会回复:
- 请求是否成功(状态码,如200 OK或404 Not Found)
- 关于回复的信息(头部,如内容类型)
- 你请求的实际内容(如HTML或JSON)
Requests库使用专门的Python对象来组织这些信息,这就是请求与响应模型。
核心组件解析
1. Request对象:你的订单
Request对象代表你想要发送的请求的基本意图。它包含:
- 目标URL
- 请求方法(GET、POST等)
- 需要添加的请求头
- 要发送的数据
虽然在使用简单的函数式API时你通常不会直接创建这个对象,但Requests库会在内部为你处理。
类比:就像你在点餐单上写下"大号披萨,意大利辣香肠,额外芝士"。
2. PreparedRequest对象:准备好的餐盘
这是请求的最终版本,已经准备好发送。Requests库会:
- 获取初始的Request对象
- 处理它(编码数据、应用cookie、添加默认头如User-Agent)
- 准备通过网络发送
它包含了将要发送的确切字节和最终细节,这主要是一个内部处理步骤。
类比:厨房根据你的点餐单制作披萨,装盒,添加餐巾纸和饮料,将所有东西放在托盘上准备交给配送员。
3. Response对象:送达的餐食
这个对象代表服务器在收到PreparedRequest后的回复。它包含:
- 状态码(订单是否成功?)
- 响应头(这是什么类型的食物?如何包装的?)
- 实际内容(披萨本身!)
这是你通常会直接与之交互的对象。
类比:配送员将装有披萨和收据的托盘交给你。你检查收据(status_code、headers)然后享用披萨(content)。
深入Response对象
让我们通过一个实际例子来探索Response对象的各个有用部分:
import requests
url = 'https://httpbin.org/get'
response = requests.get(url)
# 1. 状态码:请求是否成功?
print(f"状态码: {response.status_code}") # 数字如200(成功)或404(未找到)
print(f"是否成功(状态码<400)? {response.ok}") # 布尔值True/False
# 2. 响应头:关于响应的信息
print(f"\n响应头(Content-Type): {response.headers['Content-Type']}")
print("所有头信息:")
for key, value in response.headers.items():
print(f" {key}: {value}")
# 3. 响应内容(正文):实际数据!
# - 作为文本(使用猜测的编码解码):
print("\n响应文本(前100个字符):")
print(response.text[:100])
# - 作为原始字节(对非文本内容如图片很有用):
print("\n响应内容(字节,前20个):")
print(response.content[:20])
# 4. JSON辅助方法:如果内容是JSON
json_url = 'https://httpbin.org/json'
json_response = requests.get(json_url)
if json_response.ok and 'application/json' in json_response.headers.get('Content-Type', ''):
try:
data = json_response.json() # 将JSON解码为Python字典/列表
print("解码后的JSON数据:")
print(data)
except requests.exceptions.JSONDecodeError:
print("响应不是有效的JSON。")
Response对象的关键属性
- status_code:标准的HTTP状态码数字。200表示"OK",404表示"未找到"。
- ok:一个快速的布尔检查。如果状态码小于400(表示成功或重定向)则为True,对于错误(4xx或5xx代码)则为False。
- headers:一个类似字典的对象,包含服务器发送的响应头(如Content-Type、Date、Server)。它是大小写不敏感的。
- text:将响应体解码为字符串。Requests会尝试根据头部猜测正确的文本编码,或者根据内容本身进行猜测。适用于HTML、纯文本等。
- content:作为原始字节的响应体,与从服务器接收的完全一致。适用于图片、下载或当你需要精确控制解码时。
- json():一个便捷的方法,尝试将response.text解析为JSON并返回Python字典或列表。如果内容不是有效的JSON,则会引发错误。
内部工作原理:从请求到响应
当你调用requests.get(url)时,幕后发生了以下过程(简化版):
- 创建Request:Requests创建一个包含方法('GET')、url和你提供的其他参数(如headers或params)的Request对象。
- 准备Request:这个Request对象被传递给准备步骤,变成PreparedRequest。这包括:
- 合并会话级设置(如来自Session的默认头或cookie)
- 编码参数(params)
- 编码正文(data或json)
- 处理认证(auth)
- 添加标准头(如User-Agent、Accept-Encoding)
- 解析最终URL
- 发送PreparedRequest:包含确切字节和头的PreparedRequest被交给传输适配器,处理实际的网络通信。
- 接收回复:传输适配器等待服务器的回复(状态行、头、正文)。
- 构建Response:适配器使用原始回复数据构建你将收到的Response对象。它解析状态码、头,并使原始内容可用。
- 返回Response:send方法返回完全形成的Response对象给你的代码。
模型定义解析
Requests库中的模型定义(高度简化):
class Request:
"""用户创建的Request对象。用于准备PreparedRequest。"""
def __init__(self, method=None, url=None, headers=None, data=None):
self.method = method
self.url = url
# 其他属性...
def prepare(self):
"""构造用于传输的PreparedRequest。"""
p = PreparedRequest()
p.prepare(method=self.method, url=self.url)
return p
class PreparedRequest:
"""完全可变的PreparedRequest对象,包含将发送到服务器的确切字节。"""
def __init__(self):
self.method = None
self.url = None
self.headers = None
self.body = None
def prepare(self, method=None, url=None, headers=None, data=None):
"""准备整个请求。"""
self.method = method
self.url = url # 处理后的url
self.headers = headers # 最终头
self.body = data # 编码后的正文字节或流
class Response:
"""包含服务器对HTTP请求的响应。"""
def __init__(self):
self._content = False # 内容尚未读取
self.status_code = None
self.headers = CaseInsensitiveDict() # 头信息的特殊字典
self.raw = None # 来自网络连接的原始流
self.url = None
self.encoding = None
@property
def content(self):
"""响应的内容,以字节为单位。"""
return self._content
@property
def text(self):
"""响应的内容,以unicode表示。"""
return decoded_string
def json(self):
"""返回响应的json编码内容(如果有的话)。"""
return python_object
总结
通过本文,我们深入理解了Requests库中的核心数据载体:
- Request:你的初始意图
- PreparedRequest:准备发送的最终请求
- Response:服务器的回复,包含状态、头和内容
虽然你主要是在发起请求后与Response对象交互,但了解Request和PreparedRequest有助于理解整个过程。我们探索了Response对象的有用属性,如status_code、headers、text、content和方便的json()方法。
理解这些模型能让你更清楚地看到Requests库如何将简单的函数调用转化为网络操作,并将结果整洁地打包给你使用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



