1. 为什么选择requests模块作为Python HTTP请求的首选
在Python生态中,requests模块已经成为处理HTTP请求的事实标准。作为一个第三方库,它比Python内置的urllib更加人性化,让发送HTTP请求变得异常简单。我最初接触requests时,就被它简洁的API设计所折服 - 相比urllib那些晦涩的方法名和复杂的参数,requests用get()、post()这样的直观方法名,让代码可读性大幅提升。
requests的流行程度从PyPI的下载量就可见一斑 - 每月数亿次的下载量让它稳居Python库下载榜前列。这得益于它解决了几个核心痛点:自动处理连接池管理、支持国际域名和URL、支持带Cookie的持久会话、支持文件上传等。这些特性让开发者从底层HTTP协议的复杂性中解放出来,专注于业务逻辑的实现。
提示:虽然requests不是Python标准库的一部分,但它的稳定性和广泛使用已经让它成为"事实标准"。在生产环境中使用完全不用担心维护问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与requests安装
2.1 Python环境配置
在开始使用requests之前,确保你已经安装了Python 3.6或更高版本。可以通过命令行检查:
bash复制python --version
# 或
python3 --version
如果你看到的是Python 2.x版本,建议立即升级。Python 2已经在2020年停止支持,requests的最新版本也不再兼容Python 2。
2.2 安装requests模块
安装requests非常简单,使用pip即可:
bash复制pip install requests
如果你遇到网络问题导致安装失败(常见于国内环境),可以尝试使用国内镜像源:
bash复制pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
安装完成后,可以通过以下命令验证是否安装成功:
python复制import requests
print(requests.__version__) # 应该输出类似2.28.1的版本号
2.3 开发工具选择
虽然你可以使用任何文本编辑器编写Python代码,但我推荐使用专业的IDE或编辑器:
- VS Code:轻量级但功能强大,配合Python插件体验很好
- PyCharm:专业的Python IDE,对requests有很好的智能提示
- Jupyter Notebook:适合交互式开发和调试HTTP请求
3. requests核心API详解
3.1 GET请求 - 获取数据的基础
GET是最常用的HTTP方法,用于从服务器获取资源。requests中发送GET请求非常简单:
python复制import requests
response = requests.get('https://api.github.com/events')
print(response.status_code) # 200
print(response.text) # 返回的JSON数据
几个关键点需要注意:
status_code属性获取HTTP状态码text属性获取响应内容(自动解码)json()方法可以直接将JSON响应解析为Python字典
处理查询参数:GET请求经常需要附加查询参数。requests提供了两种方式:
python复制# 方式1:直接在URL中添加
response = requests.get('https://httpbin.org/get?key1=value1&key2=value2')
# 方式2:使用params参数(推荐)
params = {'key1': 'value1', 'key2': 'value2'}
response = requests.get('https://httpbin.org/get', params=params)
第二种方式更清晰,也避免了手动编码URL的问题。
3.2 POST请求 - 向服务器提交数据
POST请求用于向服务器提交数据,如表单提交、文件上传等。requests的POST方法同样简单易用:
python复制data = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://httpbin.org/post', data=data)
print(response.json())
对于JSON数据,可以直接使用json参数,requests会自动序列化并设置正确的Content-Type:
python复制json_data = {'name': 'John', 'age': 30}
response = requests.post('https://httpbin.org/post', json=json_data)
文件上传也是常见的POST操作:
python复制files = {'file': open('example.txt', 'rb')}
response = requests.post('https://httpbin.org/post', files=files)
3.3 其他HTTP方法
除了GET和POST,requests还支持其他HTTP方法:
python复制# PUT请求
response = requests.put('https://httpbin.org/put', data={'key': 'value'})
# DELETE请求
response = requests.delete('https://httpbin.org/delete')
# HEAD请求
response = requests.head('https://httpbin.org/get')
# OPTIONS请求
response = requests.options('https://httpbin.org/get')
4. 高级特性与实战技巧
4.1 会话(Session)管理
requests的Session对象允许你跨请求保持某些参数,如cookies、headers等。这在需要登录的网站爬取中特别有用:
python复制s = requests.Session()
# 第一次请求设置cookie
s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
# 第二次请求会自动携带cookie
response = s.get('https://httpbin.org/cookies')
print(response.text) # 会显示{"cookies":{"sessioncookie":"123456789"}}
Session还可以用来设置默认参数:
python复制s = requests.Session()
s.headers.update({'x-test': 'true'})
# 所有通过s发出的请求都会自动带上x-test头
response = s.get('https://httpbin.org/headers')
4.2 超时与重试机制
网络请求可能会因为各种原因失败,合理的超时设置和重试机制很重要:
python复制# 设置超时(连接超时和读取超时)
try:
response = requests.get('https://httpbin.org/delay/5', timeout=(3.05, 5))
except requests.exceptions.Timeout:
print("请求超时")
对于重试,可以使用urllib3的Retry结合requests的Session:
python复制from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
s = requests.Session()
retries = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
s.mount('http://', HTTPAdapter(max_retries=retries))
s.mount('https://', HTTPAdapter(max_retries=retries))
response = s.get('https://example.com')
4.3 代理设置
在某些环境下,你可能需要通过代理服务器发送请求:
python复制proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
response = requests.get('https://httpbin.org/ip', proxies=proxies)
如果需要认证的代理:
python复制proxies = {
'http': 'http://user:password@10.10.1.10:3128/',
}
4.4 SSL证书验证
默认情况下,requests会验证SSL证书。在开发环境中,你可能需要禁用验证(生产环境不推荐):
python复制response = requests.get('https://example.com', verify=False)
或者指定自定义CA证书:
python复制response = requests.get('https://example.com', verify='/path/to/cert.pem')
5. 常见问题与调试技巧
5.1 处理HTTP错误
requests不会自动处理HTTP错误状态码(如404、500等),需要手动检查:
python复制response = requests.get('https://httpbin.org/status/404')
try:
response.raise_for_status() # 如果状态码不是200,会抛出HTTPError异常
except requests.exceptions.HTTPError as err:
print(f"HTTP错误: {err}")
5.2 查看请求详情
调试时,查看实际发送的请求很有帮助:
python复制response = requests.get('https://httpbin.org/get')
print(response.request.headers) # 查看请求头
print(response.request.url) # 查看最终URL
print(response.request.body) # 查看请求体
5.3 处理429 Too Many Requests
当遇到429状态码时,表示请求过于频繁。合理的处理方式是:
python复制response = requests.get('https://httpbin.org/status/429')
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
# 重试请求
5.4 处理502 Bad Gateway
502错误通常表示服务器端问题。可以尝试:
- 检查目标服务器是否正常运行
- 增加重试机制
- 联系服务提供商
python复制try:
response = requests.get('https://example.com', timeout=10)
if response.status_code == 502:
# 实现重试逻辑
pass
except requests.exceptions.ConnectionError:
# 处理连接错误
pass
6. 性能优化与最佳实践
6.1 连接池管理
requests底层使用urllib3的连接池,合理配置可以提高性能:
python复制from requests.adapters import HTTPAdapter
s = requests.Session()
adapter = HTTPAdapter(pool_connections=10, pool_maxsize=10, max_retries=3)
s.mount('http://', adapter)
s.mount('https://', adapter)
6.2 流式响应
对于大文件下载,使用流式响应可以节省内存:
python复制response = requests.get('https://example.com/large-file', stream=True)
with open('large-file', 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
6.3 异步请求
虽然requests本身是同步的,但可以结合多线程或asyncio实现并发:
python复制import concurrent.futures
urls = ['https://example.com/1', 'https://example.com/2', 'https://example.com/3']
def fetch(url):
return requests.get(url).text
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
results = executor.map(fetch, urls)
for result in results:
print(len(result))
对于真正的异步IO,可以考虑aiohttp库。
6.4 请求批处理
当需要发送大量请求时,合理控制频率很重要:
python复制import time
urls = [...] # 大量URL列表
delay = 1 # 每秒1个请求
for url in urls:
response = requests.get(url)
# 处理响应
time.sleep(delay) # 控制请求频率
7. 实际项目中的应用案例
7.1 调用REST API
假设我们要调用GitHub API获取用户信息:
python复制import requests
from requests.auth import HTTPBasicAuth
# 基本认证
response = requests.get(
'https://api.github.com/user',
auth=HTTPBasicAuth('username', 'password')
)
# 或者使用token
headers = {'Authorization': 'token your_token_here'}
response = requests.get('https://api.github.com/user', headers=headers)
7.2 网页爬虫基础
一个简单的网页爬虫示例:
python复制from bs4 import BeautifulSoup
response = requests.get('https://example.com')
soup = BeautifulSoup(response.text, 'html.parser')
# 提取所有链接
for link in soup.find_all('a'):
print(link.get('href'))
7.3 文件下载器
实现一个带进度显示的文件下载器:
python复制import requests
import os
from tqdm import tqdm
def download_file(url, filename=None):
if filename is None:
filename = url.split('/')[-1]
with requests.get(url, stream=True) as r:
r.raise_for_status()
total_size = int(r.headers.get('content-length', 0))
with open(filename, 'wb') as f, tqdm(
desc=filename,
total=total_size,
unit='iB',
unit_scale=True,
unit_divisor=1024,
) as bar:
for chunk in r.iter_content(chunk_size=8192):
size = f.write(chunk)
bar.update(size)
return filename
download_file('https://example.com/large-file.zip')
7.4 API客户端封装
对于经常使用的API,可以封装成客户端类:
python复制class GitHubClient:
BASE_URL = 'https://api.github.com'
def __init__(self, token=None):
self.session = requests.Session()
if token:
self.session.headers.update({'Authorization': f'token {token}'})
def get_user(self, username):
url = f'{self.BASE_URL}/users/{username}'
response = self.session.get(url)
response.raise_for_status()
return response.json()
def get_repos(self, username):
url = f'{self.BASE_URL}/users/{username}/repos'
response = self.session.get(url)
response.raise_for_status()
return response.json()
# 使用示例
client = GitHubClient()
user = client.get_user('octocat')
repos = client.get_repos('octocat')
