Skip to content

第 5 章 · 响应详解

本章目标:掌握响应状态码检查、JSON 解析、二进制处理和流式响应的完整用法。

5.1 状态码检查

HTTP 状态码表示请求处理结果:

范围含义示例
2xx成功200 OK, 201 Created
3xx重定向301 Moved, 304 Not Modified
4xx客户端错误400 Bad Request, 404 Not Found
5xx服务端错误500 Internal Server Error
python
import requests

resp = requests.get('https://httpbin.org/status/404')

# 方式一:手动检查
if resp.status_code == 200:
    print('成功')
elif resp.status_code == 404:
    print('未找到')
else:
    print(f'其他状态: {resp.status_code}')

# 方式二:is_success 属性(2xx 返回 True)
if resp.is_success:
    print('成功')
else:
    print(f'失败: {resp.status_code}')

# 方式三:raise_for_status()(推荐,失败时抛异常)
resp.raise_for_status()  # 如果状态码 >= 400,抛出 HTTPError

5.2 JSON 响应处理

python
import requests
import json

resp = requests.get('https://api.github.com/users/octocat')

# 解析 JSON
data = resp.json()
print(data['name'])

# 检查是否为 JSON 响应
if resp.headers.get('Content-Type', '').startswith('application/json'):
    data = resp.json()
else:
    print('非 JSON 响应:', resp.text[:100])

# 处理 JSON 解析错误
try:
    data = resp.json()
except requests.exceptions.JSONDecodeError as e:
    print(f'JSON 解析失败: {e}')
    print('原始响应:', resp.text[:200])

5.3 二进制响应处理

适用于图片、文件、音频等:

python
import requests

# 下载图片
resp = requests.get('https://httpbin.org/image/png')

# 保存为文件
with open('download.png', 'wb') as f:
    f.write(resp.content)

# 处理内存中的二进制数据
image_data = resp.content
# 可传递给 PIL、cv2 等库处理

5.4 流式响应

处理大文件时使用 stream=True,避免一次性加载到内存:

python
import requests

# 流式下载大文件
with requests.get('https://httpbin.org/stream/20', stream=True) as resp:
    resp.raise_for_status()
    
    # 逐步读取内容
    for line in resp.iter_lines():
        if line:
            print(line.decode('utf-8'))

# 下载大文件到磁盘
url = 'https://httpbin.org/drip?numbytes=500000&delay=1'
with requests.get(url, stream=True) as resp:
    resp.raise_for_status()
    total = int(resp.headers.get('content-length', 0))
    
    with open('large_file.bin', 'wb') as f:
        for chunk in resp.iter_content(chunk_size=8192):
            if chunk:
                f.write(chunk)
                # 可选:显示进度
                # print(f'\r下载: {f.tell()}/{total}', end='')

iter_content()iter_lines() 是流式处理的关键方法。

5.5 响应超时

python
import requests

# 设置超时(秒)
try:
    resp = requests.get('https://httpbin.org/delay/5', timeout=3)
except requests.exceptions.Timeout:
    print('请求超时')

# 分别设置连接超时和读取超时
resp = requests.get(url, timeout=(5, 10))  # (connect_timeout, read_timeout)

# httpx 等效写法
import httpx
client = httpx.Client(timeout=10.0)
resp = client.get(url)

5.6 本章小结

  • 使用 resp.status_coderesp.is_success 检查状态;
  • resp.raise_for_status() 在失败时抛出异常(推荐);
  • 二进制数据用 .content,JSON 用 .json()
  • 大文件用 stream=True + iter_content() 流式处理;
  • 始终设置合理的超时时间。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. resp.raise_for_status() 在什么情况下会抛出异常?

2. 流式响应 stream=True 的主要优势是?

3. timeout 参数设置为 (5, 10) 表示?

4. 处理二进制响应(如图片)应使用哪个属性?

🛠️ 动手实践

  1. 向 httpbin 发送请求获取 404 状态,分别用三种方式检查状态码。
  2. 流式下载一个 1MB 以上的文件,记录耗时和内存使用。
  3. 设置 2 秒超时,向慢速服务器发送请求,捕获 Timeout 异常。