在现代网络爬虫和API交互中,简单的GET/POST请求往往不能满足需求。本文将深入探讨Python requests库的高级特性,包括状态保持、会话管理以及常见异常处理,帮助你更好地模拟浏览器行为,完成复杂的网页采集任务。
HTTP协议是无状态的,这意味着服务器不会记住之前的请求信息。Cookie的引入解决了这个问题,它允许服务器在客户端存储少量信息,并在后续请求中携带这些信息。
Cookie的主要用途:
用户身份验证(如登录状态保持)
个性化设置存储
会话跟踪
行为分析
Requests提供了两种使用Cookie的方式:
import requests
url = 'https://example.com/protected-page'
headers = {
'Cookie': 'session_id=12345; user_token=abcde',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
}
response = requests.get(url, headers=headers)
print(response.text)
import requests
url = 'https://example.com/protected-page'
cookies = {
'session_id': '12345',
'user_token': 'abcde'
}
response = requests.get(url, cookies=cookies)
print(response.text)
推荐使用第二种方式,因为:
字典格式更易维护和修改
可以避免Cookie字符串格式错误
方便动态更新Cookie值
Session通过在多个请求间保持某些参数(如Cookie)来实现状态保持。这在需要登录后才能访问的网站中特别有用。
import requests
# 创建Session对象
session = requests.Session()
# 第一次请求:登录并设置Cookie
login_url = 'https://example.com/login'
login_data = {'username': 'admin', 'password': '123456'}
session.post(login_url, data=login_data)
# 第二次请求:访问受保护页面,自动携带Cookie
protected_url = 'https://example.com/dashboard'
response = session.get(protected_url)
print(response.text)
关键点:
Session会自动处理服务器设置的Cookie
后续请求无需手动添加Cookie
适合需要多次交互的场景(如表单提交、验证码处理)
import requests
import time
def get_timestamp():
"""获取当前毫秒级时间戳"""
return str(int(time.time() * 1000))
# 创建Session
session = requests.Session()
headers = {'User-Agent': 'Mozilla/5.0'}
# 1. 获取验证码图片
timestamp = get_timestamp()
captcha_url = f'https://example.com/captcha?t={timestamp}'
captcha_response = session.get(captcha_url, headers=headers)
# 保存验证码图片
with open('captcha.jpg', 'wb') as f:
f.write(captcha_response.content)
# 2. 用户输入验证码
captcha_code = input('请输入验证码: ')
# 3. 提交登录请求
login_url = 'https://example.com/login'
login_data = {
'username': 'admin',
'password': '123456',
'captcha': captcha_code
}
login_response = session.post(login_url, data=login_data, headers=headers)
print('登录结果:', login_response.json())
response = requests.get('https://example.com')
# 自动检测编码
response.encoding = response.apparent_encoding
print(response.text)
常见错误:请求头中包含非法字符(如多余空格)
# 错误示例(User-Agent前有空格)
headers = {
'User-Agent': ' Mozilla/5.0' # 注意开头的空格
}
# 正确写法
headers = {
'User-Agent': 'Mozilla/5.0' # 无多余空格
}
try:
response = requests.get('https://example.com', timeout=5)
print(response.text)
except requests.exceptions.Timeout:
print("请求超时,请检查网络连接或增加超时时间")
except requests.exceptions.RequestException as e:
print(f"请求发生错误: {e}")
try:
response = requests.get('http://invalid-url:9999')
except requests.exceptions.ConnectionError:
print("无法连接到服务器,可能是URL错误或服务器未运行")
import requests
def baidu_translate(query, from_lang='zh', to_lang='en'):
url = 'https://fanyi.baidu.com/v2transapi'
headers = {
'Host': 'fanyi.baidu.com',
'Origin': 'https://fanyi.baidu.com',
'Referer': 'https://fanyi.baidu.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
}
data = {
'from': from_lang,
'to': to_lang,
'query': query,
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '232427.485594', # 这个值通常需要动态生成
'token': '5e393efd8ddbab20a2afa0cfe318606c' # 需要从页面获取
}
# 实际使用中需要从浏览器获取有效的Cookie
cookies = {
'BAIDUID': 'XXXXXXXXXXXX:FG=1',
'BDUSS': 'XXXXXXXXXXXX',
# 其他必要的Cookie项
}
try:
response = requests.post(url, headers=headers, data=data, cookies=cookies)
response.raise_for_status() # 检查请求是否成功
return response.json()
except requests.exceptions.RequestException as e:
print(f"翻译请求失败: {e}")
return None
# 使用示例
result = baidu_translate('你好')
if result:
print('翻译结果:', result['trans_result']['data'][0]['dst'])
注意:实际使用时,需要从浏览器获取有效的token和sign值,以及完整的Cookie。
Cookie安全:不要将含有敏感信息的Cookie提交到版本控制系统
请求频率:合理设置请求间隔,避免被封禁
错误处理:对所有网络请求添加异常处理
超时设置:为所有请求设置合理的超时时间
Session复用:对于同一站点的多次请求,尽量复用Session对象
编码处理:始终检查并正确设置响应编码