别再被反爬了!手把手教你用Python requests库搞定Headers和Cookies(附B站实战)
·
Python爬虫实战:深度解析Headers与Cookies反反爬策略
当你的爬虫程序突然返回403 Forbidden时,那种挫败感每个开发者都深有体会。上周我帮一个电商客户抓取公开商品数据时,连续3天被同一个网站封锁,直到发现他们的反爬系统会检测Accept-Language字段的异常组合。这让我意识到,Headers和Cookies的细节处理远比想象中复杂得多。
1. 反爬机制原理与突破思路
现代网站的反爬系统就像机场安检,会检查每个"旅客"的"证件"(Headers)和"行程记录"(Cookies)。以B站为例,其风控系统会通过多层验证:
-
基础验证层:检查必填字段是否存在
User-Agent必须来自主流浏览器Referer必须符合跳转逻辑Accept-Encoding必须包含gzip
-
行为分析层:检测异常访问模式
- 相同Cookies的高频请求
- 缺少
X-Requested-With的AJAX请求 - 非常规的Header字段顺序
-
高级验证层(动态触发):
- 鼠标轨迹验证(通过JavaScript)
- WebSocket指纹检测
- TLS指纹识别
# 典型被拦截的请求示例
import requests
url = 'https://www.bilibili.com/v/popular/rank/all'
response = requests.get(url) # 403概率90%
print(response.status_code)
提示:现代反爬系统会建立请求特征的基线模型,任何偏离正常浏览器行为的特征都会被标记
2. 开发者工具实战:获取真实请求参数
Chrome开发者工具(F12)是获取Headers的瑞士军刀,但大多数人只用到表面功能。以下是专业爬虫工程师的实操流程:
2.1 高级捕获技巧
- 打开无痕窗口(避免插件干扰)
- 清除所有缓存(Ctrl+Shift+Del)
- 在Network面板中:
- 勾选"Preserve log"
- 设置"Recording network log"为Always
- 添加自定义Header过滤器
# 从浏览器复制完整cookies的转换代码
def parse_cookie_string(cookie_str):
return {item.split('=')[0]: item.split('=')[1]
for item in cookie_str.split('; ')}
2.2 关键Header字段解析
| 字段名 | 作用 | 伪装要点 |
|---|---|---|
| User-Agent | 客户端标识 | 使用最新版Chrome UA |
| Accept-Language | 语言偏好 | 匹配目标用户地区 |
| Sec-CH-UA | 浏览器品牌提示 | 需完整平台标识 |
| Upgrade-Insecure-Requests | HTTPS升级请求 | 通常设为1 |
| X-Requested-With | AJAX请求标记 | XMLHttpRequest |
注意:某些字段如
Sec-Fetch-*系列不能随意修改,错误的组合会直接触发防护
3. 动态Cookies处理方案
很多教程教你把Cookie直接硬编码,这在2023年已经行不通了。以B站登录为例,其Cookie包含多个动态参数:
bili_jct:CSRF tokenSESSDATA:会话密钥DedeUserID:用户IDsid:临时会话ID
# 动态维持Cookie会话的示例
session = requests.Session()
login_url = 'https://passport.bilibili.com/login'
# 首次获取验证参数
pre_login = session.get(login_url)
token = re.search(r'name="csrf" value="(.*?)"', pre_login.text).group(1)
# 模拟登录
form_data = {
'username': 'your_username',
'password': 'your_password',
'csrf': token
}
session.post(login_url, data=form_data)
# 后续请求自动携带Cookies
profile = session.get('https://space.bilibili.com/')
常见动态Cookie更新策略:
- 定时刷新
refresh_token - 处理
Set-Cookie响应头 - 监控Cookie过期时间
- 备用账号轮换机制
4. 高级伪装与反检测技巧
4.1 请求指纹混淆
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br', # 注意顺序
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1'
}
4.2 请求随机化策略
-
延迟策略:
- 正态分布随机延迟(均值2-3秒)
- 页面深度相关延迟
- 失败请求的指数退避
-
流量模拟策略:
- 随机浏览路径生成
- 模拟鼠标移动轨迹
- 添加无操作停留时间
# 智能延迟示例
import random
import time
def smart_delay(last_request_time):
base_interval = 2.5 # 基础间隔
jitter = random.gauss(0, 0.5) # 正态分布抖动
elapsed = time.time() - last_request_time
wait_time = max(0, base_interval - elapsed + jitter)
time.sleep(wait_time)
return time.time()
5. 异常处理与调试技巧
当遇到403/429状态码时,专业开发者会这样排查:
-
请求对比分析:
- 用Burp Suite捕获正常请求
- 使用Diff工具对比Header差异
- 检查Cookie更新时序
-
动态参数追踪:
def debug_requests(response): print("Request Headers:", response.request.headers) print("Response Headers:", response.headers) print("Cookies:", session.cookies.get_dict()) if response.status_code != 200: with open('error.html', 'w', encoding='utf-8') as f: f.write(response.text) -
IP轮换方案:
- 住宅代理服务优选
- 每个IP的请求频率控制
- 自动切换触发条件设置
在最近的一个跨境电商项目中,通过组合使用这些技术,我们将请求成功率从37%提升到了92%。关键发现是目标网站会检测Accept-Encoding字段的字母大小写模式,这提醒我们——魔鬼永远藏在细节里。
更多推荐


所有评论(0)