Python Requests 库:让 HTTP 请求优雅起来
Requests 是 Python 生态中最受欢迎的 HTTP 库之一,它的设计哲学是「HTTP for Humans」——简单、直观,让你专注于业务逻辑而非繁琐的网络细节。相比于内置的 urllib,Requests 的接口更加人性化,能轻松处理各种 HTTP 请求与响应。
无论你是在开发爬虫、调用 RESTful API,还是需要与第三方服务交互,Requests 都能大大提升你的开发效率。
1. 安装与起步
使用 pip 即可完成安装:
如果你在使用 Anaconda 环境,Requests 通常已经预装好了。若遇到权限问题,可以加上 --user 参数或将 pip 运行在虚拟环境内:
pip install --user requests
提示:推荐在虚拟环境(如 venv、conda)中管理依赖,避免污染系统级 Python。
安装后,导入库即可开始使用:
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 已经足够优雅和强大了。