Python Requests 库:让 HTTP 请求优雅起来

Requests 是 Python 生态中最受欢迎的 HTTP 库之一,它的设计哲学是「HTTP for Humans」——简单、直观,让你专注于业务逻辑而非繁琐的网络细节。相比于内置的 urllib,Requests 的接口更加人性化,能轻松处理各种 HTTP 请求与响应。

无论你是在开发爬虫、调用 RESTful API,还是需要与第三方服务交互,Requests 都能大大提升你的开发效率。

1. 安装与起步

使用 pip 即可完成安装:

pip install requests

如果你在使用 Anaconda 环境,Requests 通常已经预装好了。若遇到权限问题,可以加上 --user 参数或将 pip 运行在虚拟环境内:

pip install --user requests

提示:推荐在虚拟环境(如 venvconda)中管理依赖,避免污染系统级 Python。

安装后,导入库即可开始使用:

import requests

2. 发送第一个 GET 请求

HTTP 中最常见的操作就是 GET 请求,用于获取资源。只需一行代码就能发起请求:

response = requests.get('https://www.example.com/')

请求完成后,我们最关心的通常是状态码和响应内容:

print(response.status_code)   # 200 表示成功
print(response.text)          # 响应的 HTML 或文本内容
  • .status_code:HTTP 状态码,200 代表成功,404 表示未找到,500 是服务器错误等。
  • .text:Requests 自动解码的文本内容,通常已是可读的字符串。

2.1 携带查询参数

很多 API 需要传递查询字符串参数。Requests 可以接收一个字典,并自动拼接成 URL 参数:

params = {'q': 'python', 'page': 1}
response = requests.get('https://www.example.com/search', params=params)

print(response.url)  # 实际请求地址:https://www.example.com/search?q=python&page=1

这种方式让我不用手动拼接 ?q=python&page=1,既清晰又能避免编码问题。

3. 响应内容的处理

Requests 提供了多种方式提取响应数据,适用于不同场景:

# 原始字节数据(适用于图片、文件等)
content = response.content

# 自动解码后的文本
text = response.text

# 若响应是 JSON,直接解析成字典
data = response.json()

# 查看当前使用的字符编码
print(response.encoding)  # 通常为 'utf-8'

# 必要时可以手动指定编码
response.encoding = 'utf-8'
  • .content:返回 bytes,适合处理图片、PDF 等二进制文件。
  • .text:返回字符串,Requests 会根据响应头或 encoding 属性自动解码。
  • .json():如果响应体是 JSON 格式,可以直接调用该方法得到 Python 数据结构,省去手动 json.loads()

4. 自定义请求头

许多场景需要伪装 User-Agent 或添加认证令牌等。通过 headers 参数可以轻松设置:

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
    'Authorization': 'Bearer your_token_here'
}
response = requests.get('https://api.example.com/data', headers=headers)

Headers 中的键大小写无关紧要,Requests 会自动处理为标准格式。

5. 发送 POST 请求

POST 请求用于提交数据,比如登录、表单提交或创建资源。

5.1 表单数据

提交 application/x-www-form-urlencoded 格式的数据(模拟 HTML 表单):

data = {'username': 'admin', 'password': 'secret'}
response = requests.post('https://example.com/login', data=data)

5.2 提交 JSON 数据

现在 REST API 大多使用 JSON,可以直接使用 json 参数,Requests 会自动设置 Content-Type: application/json

json_data = {'name': 'Alice', 'age': 30}
response = requests.post('https://api.example.com/users', json=json_data)

5.3 文件上传

上传文件时,使用 files 参数,并以二进制模式打开文件:

with open('report.pdf', 'rb') as f:
    files = {'file': f}
    response = requests.post('https://example.com/upload', files=files)

注意 'rb' 模式,否则可能因编码问题损坏文件。files 字典支持多文件同时上传。

6. 其它 HTTP 方法

Requests 为常见 HTTP 方法都提供了对应的快捷函数:

# 更新资源 (PUT)
response = requests.put('https://api.example.com/item/1', data={'name': 'new'})

# 删除资源 (DELETE)
response = requests.delete('https://api.example.com/item/1')

# 获取响应头信息 (HEAD)
response = requests.head('https://www.example.com')

# 查询服务器支持的请求方法 (OPTIONS)
response = requests.options('https://api.example.com')

这些方法用法与 get()post() 高度一致,参数通用。

7. 响应头与 Cookies

7.1 查看响应头

响应头以字典形式存储在 response.headers 中,键不区分大小写:

print(response.headers['Content-Type'])  # 'text/html; charset=utf-8'
print(response.headers.get('Server'))    # 获取服务器类型

7.2 处理 Cookies

服务端返回的 Cookie 可以通过 response.cookies 访问;发送请求时也可以携带自定义 Cookie:

# 获取响应中的 Cookie
print(response.cookies['session_id'])

# 在请求中带上 Cookie
cookies = {'session_id': 'abc123'}
response = requests.get('https://example.com/dashboard', cookies=cookies)

8. 超时控制

网络请求可能会因为网络波动或服务器无响应而一直阻塞。设置 timeout 可以限制等待时间,避免程序卡死:

try:
    response = requests.get('https://example.com', timeout=3)  # 3 秒超时
except requests.exceptions.Timeout:
    print("请求超时,请检查网络或增加超时时间")

建议在所有请求中都显式设置超时时间,提升程序的健壮性。

9. 保持会话:Session 对象

如果需要多次请求同一个网站,并保持登录状态或公共请求头,可以使用 Session 对象:

session = requests.Session()
session.headers.update({'User-Agent': 'MyApp/1.0'})

# 登录(假设 POST 后会设置 session cookie)
session.post('https://example.com/login', data={'user': 'me', 'pass': '123'})

# 后续请求自动携带 cookie 和 headers
response = session.get('https://example.com/profile')

Session 底层使用了连接池,跨请求时还会复用 TCP 连接,提升性能。

10. 高级功能速览

10.1 重定向处理

默认情况下,Requests 会自动跟随 3xx 重定向。如果想禁止自动跳转,可以设置 allow_redirects=False

response = requests.get('https://example.com', allow_redirects=False)
# 查看重定向历史
print(response.history)

10.2 使用代理

通过 proxies 参数配置 HTTP/HTTPS 代理:

proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.10:1080',
}
response = requests.get('https://api.example.com', proxies=proxies)

10.3 SSL 证书验证

访问 HTTPS 站点时,Requests 默认会验证 SSL 证书。若在开发环境中遇到自签名证书,可以暂时关闭验证(生产环境切勿这么做),或指定自定义 CA 证书:

# 临时关闭验证
response = requests.get('https://example.com', verify=False)

# 使用自定义 CA 证书
response = requests.get('https://example.com', verify='/path/to/cert.pem')

11. 错误处理的最佳实践

网络操作中异常难以避免,完善的错误处理能让程序更可靠:

try:
    response = requests.get('https://example.com', timeout=5)
    response.raise_for_status()   # 检查 HTTP 状态码,4xx/5xx 会抛出异常
except requests.exceptions.HTTPError as e:
    print(f"HTTP 错误: {e}")
except requests.exceptions.ConnectionError as e:
    print(f"连接错误: {e}")
except requests.exceptions.Timeout as e:
    print(f"请求超时: {e}")
except requests.exceptions.RequestException as e:
    print(f"其他请求异常: {e}")
  • raise_for_status() 会在状态码为 4xx 或 5xx 时抛出 HTTPError,省去手动检查。
  • 所有 Requests 异常都继承自 requests.exceptions.RequestException

12. 性能优化小贴士

12.1 流式下载大文件

下载大文件时,使用 stream=True 可以边下载边写入磁盘,避免一次性加载到内存:

response = requests.get('https://example.com/bigfile.zip', stream=True)
with open('bigfile.zip', 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        f.write(chunk)

12.2 调整连接池

通过自定义 HTTPAdapter,可以控制连接池大小和重试策略:

from requests.adapters import HTTPAdapter

session = requests.Session()
adapter = HTTPAdapter(
    pool_connections=10,
    pool_maxsize=10,
    max_retries=3
)
session.mount('https://', adapter)
session.mount('http://', adapter)

这对于高并发请求场景非常有用。

13. 总结

Requests 将 HTTP 的复杂性封装在简洁的 API 之后,让你可以:

  • 用极少的代码完成 GET、POST 等常见操作;
  • 轻松处理 JSON、文件上传、Cookies 和 Headers;
  • 通过 Session 保持登录状态和复用连接;
  • 利用超时、exception-handling、流式请求等机制构建稳定的网络程序。

掌握这些核心功能后,你就可以在实际项目中得心应手地使用 Requests 了。如果想进一步探索,推荐查阅官方文档和《HTTP 权威指南》以理解底层协议——当然,日常开发中,Requests 已经足够优雅和强大了。