1. 请求头在爬虫中的核心作用
请求头(Headers)是HTTP协议中客户端发送给服务器的元信息集合,它决定了服务器如何看待和处理这次请求。对于爬虫开发者而言,正确配置请求头是突破基础反爬机制的第一道门槛。
当使用Python的requests库发起请求时,默认的请求头会明确暴露爬虫身份:
python复制{
'User-Agent': 'python-requests/2.26.0',
'Accept-Encoding': 'gzip, deflate',
'Accept': '*/*',
'Connection': 'keep-alive'
}
这种特征明显的请求头会导致:
- 服务器直接拒绝响应(返回403状态码)
- 触发验证码机制
- 被列入临时黑名单
- 获取到与浏览器访问不同的页面内容(针对爬虫的特定响应)
实际案例:某电商网站对未设置User-Agent的请求返回简化版HTML,关键商品数据全部缺失。添加浏览器UA后立即获取完整页面。
2. 关键请求头字段详解
2.1 基础伪装四件套
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br'
}
-
User-Agent:最核心的字段,建议:
- 使用最新版Chrome/Firefox的UA
- 通过
navigator.userAgent获取真实浏览器UA - 避免使用过时版本(如Chrome 80以下)
-
Accept:声明可接受的响应类型,现代浏览器通常包含webp图片支持
-
Accept-Language:语言偏好设置,中文站点建议保留zh-CN
-
Accept-Encoding:压缩算法支持,注意服务端可能根据此字段返回压缩内容
2.2 进阶防护字段
python复制headers.update({
'Sec-Ch-Ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
'Sec-Ch-Ua-Mobile': '?0',
'Sec-Ch-Ua-Platform': '"Windows"',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-User': '?1',
'Sec-Fetch-Dest': 'document'
})
这些安全相关头部是Chrome 90+新增的防御机制,缺少它们可能导致:
- 被识别为"非浏览器流量"
- 触发Cloudflare等防护系统的验证
- 无法获取完整页面资源
3. 动态请求头实战技巧
3.1 User-Agent轮换策略
固定UA仍可能被识别,推荐方案:
python复制from fake_useragent import UserAgent
import random
def get_random_ua():
ua = UserAgent()
return {
'mobile': ua.google,
'pc': ua.chrome
}[random.choice(['mobile', 'pc'])]
踩坑记录:某新闻网站对iOS设备的UA返回移动版页面,导致XPath定位失效。解决方案是保持UA与目标页面版本一致。
3.2 Cookie与Token处理
需要保持会话时:
python复制session = requests.Session()
session.headers.update({
'Cookie': '_ga=GA1.1.1234567890; _gid=GA1.1.987654321',
'X-CSRF-Token': 'abcdef123456'
})
关键点:
- 通过浏览器开发者工具复制完整Cookie
- 注意Token的时效性(通常2-4小时)
- 使用Session对象维持会话状态
3.3 反反爬特殊头
某些网站需要特定头部:
python复制headers['Referer'] = 'https://www.target-site.com/'
headers['Origin'] = 'https://www.target-site.com'
headers['X-Requested-With'] = 'XMLHttpRequest' # 对AJAX请求必需
4. 请求头调试方法论
4.1 浏览器对比法
- 使用Chrome访问目标页面
- 复制Network标签中的全部请求头
- 与爬虫请求头逐字段对比
- 特别关注:
- 大小写差异(如Accept-Encoding vs accept-encoding)
- 字段顺序
- 特殊值(如Sec-Fetch-*系列)
4.2 增量测试法
python复制base_headers = {'User-Agent': '...'}
def test_headers(url):
response = requests.get(url, headers=base_headers)
if response.status_code == 403:
base_headers.update({'Accept-Language': 'zh-CN'})
response = requests.get(url, headers=base_headers)
# 继续添加其他必要头部...
return response
4.3 请求头验证工具
python复制def validate_headers(target_url):
real_headers = get_browser_headers() # 从浏览器复制
my_headers = {...} # 你的请求头
diff = set(real_headers.items()) - set(my_headers.items())
print(f"缺失头部:{diff}")
# 自动补全差异
my_headers.update(diff)
return requests.get(target_url, headers=my_headers)
5. 高级防护场景应对
5.1 指纹浏览器检测
现代反爬系统会通过以下方式检测:
- HTTP头排列顺序
- TLS指纹
- 浏览器API支持情况
解决方案:
- 使用undetected-chromedriver
- 配合selwire修改指纹
- 避免在头中包含矛盾信息(如Windows平台却发送Mac的UA)
5.2 移动端请求模拟
移动端特有头部:
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36',
'X-Requested-With': 'com.android.browser',
'X-Wap-Profile': 'http://wap.samsungmobile.com/uaprof/SM-G981B.xml'
}
5.3 协议级伪装
使用curl_cffi库模拟TLS指纹:
python复制from curl_cffi import requests
response = requests.get(
"https://target.com",
headers=headers,
impersonate="chrome110" # 模拟Chrome的TLS指纹
)
6. 实战问题排查指南
6.1 403 Forbidden错误排查流程
- 检查基础UA是否设置
- 验证Referer是否必需
- 测试Cookie是否过期
- 对比浏览器请求头差异
- 尝试降低请求频率
6.2 请求头导致的解析失败
典型表现:
- 获取到验证码页面
- HTML结构异常
- 关键数据为空白
解决方案:
- 使用diff工具对比响应内容
- 检查Content-Type是否为text/html
- 确认没有触发重定向
6.3 动态Token处理
自动化获取流程:
python复制def get_auth_token():
login_page = session.get(login_url)
token = re.search(r'name="_token" value="(.*?)"', login_page.text).group(1)
session.headers.update({'X-CSRF-TOKEN': token})
7. 性能优化与最佳实践
7.1 头部长度的取舍
不必要的头部会增加:
- 网络传输开销
- 解析处理时间
- 被识别的风险
建议保留的核心头部:
- User-Agent
- Accept
- Accept-Language
- Referer(如需)
7.2 连接复用配置
python复制session = requests.Session()
session.headers.update({
'Connection': 'keep-alive',
'Keep-Alive': 'timeout=30, max=100'
})
7.3 智能降级策略
当遭遇严格反爬时:
- 先尝试完整浏览器头
- 逐步移除非必要头部
- 最终保留最小可行集:
python复制minimal_headers = { 'User-Agent': '...', 'Accept': 'text/html' }
8. 法律与伦理边界
8.1 robots.txt合规检查
python复制from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url('https://target.com/robots.txt')
rp.read()
if not rp.can_fetch('MyBot', target_url):
raise Exception('Crawling prohibited by robots.txt')
8.2 请求频率控制
推荐爬取间隔:
- 新闻类站点:≥3秒
- 电商平台:≥5秒
- 社交媒体:≥10秒
实现方案:
python复制import time
def throttled_request(url):
time.sleep(random.uniform(2.5, 5.0))
return session.get(url)
8.3 数据使用限制
应避免:
- 大规模采集个人隐私数据
- 突破付费墙获取内容
- 对服务器造成明显负载
9. 工具与资源推荐
9.1 请求头生成工具
- Chrome开发者工具(Network标签)
- Postman的代码生成功能
- https://httpbin.org/headers 验证工具
9.2 常用Python库
python复制pip install fake-useragent curl-cffi undetected-chromedriver
9.3 浏览器头数据库
- https://developers.whatismybrowser.com/
- https://user-agents.net/
- 各浏览器官方文档
10. 持续演进策略
- 每月更新UA数据库
- 监控目标网站头部变化
- 建立请求头异常检测机制
- 维护不同站点的最优头配置表
python复制header_profiles = {
'ecommerce': {...},
'social_media': {...},
'news': {...}
}
def get_site_headers(site_type):
return header_profiles.get(site_type, default_headers)
