Python 爬虫进阶技巧:自定义请求头模拟真实浏览器访问
本文系统讲解Python爬虫如何通过模拟浏览器请求头突破网站反爬机制。首先解析HTTP请求头核心字段(如User-Agent、Referer、Sec-Fetch-*等)及其反爬识别逻辑,随后以知乎热榜为例演示基础/进阶请求头构建方法,包括完整Chrome请求头模拟和Sec-Fetch系列字段应用。进一步提出高级优化方案:构建多浏览器请求头池实现随机切换,动态生成请求头适配最新浏览器版本,并给出结合
2026年第二届人工智能与产品设计国际学术会议 (AIPD 2026)

时间:2026年02月06-08日
地点:中国-北京


前言
在 Python 爬虫开发中,请求被目标网站识别为 “非人类访问” 是最常见的反爬门槛之一。服务器通过分析 HTTP 请求头中的特征字段(如 User-Agent、Referer、Cookie 等),可以轻易区分普通浏览器请求和爬虫程序请求。本文聚焦 “自定义请求头模拟真实浏览器” 这一核心进阶技巧,从 HTTP 请求头的底层原理出发,拆解浏览器请求头的构成逻辑,结合实战案例讲解如何构建高仿真度的请求头,突破基础反爬机制,同时提供请求头池、动态适配等高级优化方案,帮助开发者打造更稳定、更隐蔽的爬虫程序。
摘要
本文以知乎热榜页面为实战对象(实战链接:知乎热榜),系统讲解 HTTP 请求头的核心字段含义、浏览器请求头的模拟方法及反爬规避策略。全文包含请求头字段解析表、基础 / 进阶模拟代码、请求头池构建、动态适配不同浏览器等核心内容,所有代码均经过实测验证,可直接复用,适用于各类网站的基础反爬突破场景。
一、HTTP 请求头核心原理
1.1 请求头的作用与反爬关联
HTTP 请求头是客户端(浏览器 / 爬虫)向服务器发送请求时附带的元数据,包含客户端身份、请求来源、数据格式等关键信息。服务器通过校验这些字段的合法性、完整性、合理性,判断请求是否来自真实浏览器:
- 缺失关键字段(如 User-Agent)→ 直接判定为爬虫,返回 403/503 错误;
- 字段值为默认值 / 异常值(如 User-Agent 为
python-requests/2.28.0)→ 直接拦截; - 字段组合不符合浏览器特征(如仅有 User-Agent,无 Accept-Language、Sec-Fetch-* 等现代浏览器字段)→ 标记为可疑请求,限制访问频率。
1.2 浏览器核心请求头字段解析
| 字段名称 | 核心作用 | 示例值 | 反爬识别关键点 |
|---|---|---|---|
| User-Agent (UA) | 标识客户端类型(浏览器 / 系统 / 版本) | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 | 爬虫默认 UA 为python-requests/x.x.x,极易被识别 |
| Referer | 标识请求来源页面 | https://www.zhihu.com/ | 跨域请求无 Referer 或 Referer 与目标域名不符,易被判定为爬虫 |
| 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 | 缺失或为异常语言(如仅 en),不符合中文网站访问特征 |
| Accept-Encoding | 标识客户端支持的压缩格式 | gzip, deflate, br | 缺失或格式错误,暴露非浏览器特征 |
| Sec-Fetch-Site | 标识请求发起的站点上下文 | same-origin / same-site / cross-site | 现代浏览器必带字段,缺失则判定为老旧客户端 / 爬虫 |
| Sec-Fetch-Mode | 标识请求模式 | navigate / no-cors / cors | 与 Sec-Fetch-Site 配合验证浏览器行为 |
| Sec-Fetch-Dest | 标识请求目标类型 | document / empty / script | 现代浏览器核心特征字段 |
| Cookie | 标识用户会话 | _zap=xxx; d_c0=xxx; | 无 Cookie 或 Cookie 长期不变,易被判定为爬虫 |
| Connection | 标识连接类型 | keep-alive | 爬虫默认可能为 close,不符合浏览器习惯 |
| Cache-Control | 标识缓存策略 | max-age=0 | 缺失则不符合浏览器请求规范 |
1.3 浏览器请求头的特征规律
- 完整性:现代浏览器(Chrome/Firefox/Edge)的请求头包含 20 + 字段,远多于爬虫默认的 5-8 个;
- 关联性:字段值存在逻辑关联(如 Chrome 的 UA 对应特定的 Sec-Fetch-* 字段值);
- 动态性:不同浏览器、不同版本、不同设备的请求头存在差异,单一固定请求头易被识别;
- 时效性:浏览器版本迭代会更新 UA 等字段,过时的 UA 值(如 Chrome 80)易被标记为异常。
二、基础实战:模拟 Chrome 浏览器请求知乎热榜
2.1 环境准备
无需额外安装依赖(使用 Python 内置的 requests 库),确认 requests 版本≥2.28.0:
bash
运行
pip install requests --upgrade
2.2 反例:未自定义请求头的爬虫(易被拦截)
2.2.1 核心代码
python
运行
import requests
# 未自定义请求头,使用requests默认配置
def crawler_no_headers():
url = "https://www.zhihu.com/hot"
try:
# 直接发送请求,无自定义请求头
response = requests.get(url, timeout=10)
print(f"响应状态码:{response.status_code}")
print(f"响应内容长度:{len(response.text)}")
except Exception as e:
print(f"请求失败:{e}")
if __name__ == "__main__":
crawler_no_headers()
2.2.2 输出结果
plaintext
响应状态码:403
响应内容长度:1024
2.2.3 原因分析
requests 默认请求头仅包含User-Agent: python-requests/2.28.1、Accept-Encoding: gzip, deflate等少量字段,知乎服务器通过 UA 字段直接识别为爬虫,返回 403 Forbidden 错误,拒绝提供数据。
2.3 正例:自定义基础请求头模拟 Chrome
2.3.1 核心代码
python
运行
import requests
def crawler_basic_headers():
url = "https://www.zhihu.com/hot"
# 自定义Chrome浏览器基础请求头
headers = {
# 核心UA字段:模拟Chrome 120 Windows 10
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
# 请求来源:知乎首页
"Referer": "https://www.zhihu.com/",
# 可接受的响应格式
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
# 语言偏好:中文优先
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
# 支持的压缩格式
"Accept-Encoding": "gzip, deflate, br",
# 连接类型:长连接
"Connection": "keep-alive",
# 缓存策略:不使用缓存
"Cache-Control": "max-age=0",
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status() # 抛出HTTP异常
print(f"响应状态码:{response.status_code}")
print(f"响应内容前500字符:\n{response.text[:500]}")
except requests.exceptions.HTTPError as e:
print(f"HTTP请求错误:{e}")
except Exception as e:
print(f"请求失败:{e}")
if __name__ == "__main__":
crawler_basic_headers()
2.3.2 输出结果
plaintext
响应状态码:200
响应内容前500字符:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>知乎热榜-知乎</title>
<meta name="keywords" content="知乎热榜,热点话题,实时热点,热门新闻,热点事件,知乎热搜榜">
<meta name="description" content="知乎热榜提供最新、最热门的话题,讨论和精华问答,让你了解当下最火的热点事件、实时热搜榜、热门新闻和热门话题。">
<link rel="shortcut icon" href="https://static.zhihu.com/heifetz/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" sizes="180x180" href="https://static.zhihu.com/heifetz/apple-touch-icon.png">
<link rel="mask-icon" href="https://static.zhihu.com/heifetz/safari-pinned-tab.svg" color="#0084FF">
<link rel="stylesheet" href="https://static.zhihu.com/heifetz/main.9f
2.3.3 核心原理说明
- UA 字段精准模拟:使用 Chrome 120 最新版的 UA 值,匹配真实浏览器的标识格式;
- 字段完整性:覆盖 Accept、Accept-Language、Referer 等核心字段,符合浏览器请求特征;
- 字段关联性:Referer 设置为知乎首页,模拟从首页点击进入热榜的真实行为;
- 格式规范性:所有字段值严格遵循 HTTP 协议规范(如 Accept 的 q 值权重、Accept-Encoding 的压缩格式顺序)。
2.4 进阶:模拟现代浏览器完整请求头(含 Sec-Fetch-* 字段)
2.4.1 核心代码
python
运行
import requests
def crawler_advanced_headers():
url = "https://www.zhihu.com/hot"
# 模拟Chrome 120完整请求头(含现代浏览器专属字段)
headers = {
# 基础标识字段
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://www.zhihu.com/",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Cache-Control": "max-age=0",
# 现代浏览器Sec-Fetch系列字段(关键反爬规避)
"Sec-Fetch-Site": "same-origin", # 同站请求
"Sec-Fetch-Mode": "navigate", # 导航模式(页面跳转)
"Sec-Fetch-Dest": "document", # 请求目标为文档
"Sec-Fetch-User": "?1", # 表示用户主动触发的请求
# 其他增强字段
"Upgrade-Insecure-Requests": "1", # 强制HTTPS
"DNT": "1", # 禁止跟踪
"Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"', # Chrome专属UA扩展
"Sec-Ch-Ua-Mobile": "?0", # 非移动设备
"Sec-Ch-Ua-Platform": '"Windows"', # 平台为Windows
}
try:
# 禁用重定向跟踪,避免请求头丢失
response = requests.get(
url,
headers=headers,
timeout=10,
allow_redirects=True
)
response.raise_for_status()
print(f"响应状态码:{response.status_code}")
# 验证是否成功获取热榜数据(查找热榜标题关键词)
if "知乎热榜" in response.text:
print("✅ 成功模拟现代浏览器请求,获取完整热榜页面")
else:
print("❌ 未获取到有效热榜数据")
except Exception as e:
print(f"请求失败:{e}")
if __name__ == "__main__":
crawler_advanced_headers()
2.4.2 输出结果
plaintext
响应状态码:200
✅ 成功模拟现代浏览器请求,获取完整热榜页面
2.4.3 核心原理说明
- Sec-Fetch 系列字段:这是 Chrome 80 + 版本新增的核心字段,用于标识请求的上下文特征,缺失这些字段的请求会被服务器判定为 “非现代浏览器”,是突破中高级反爬的关键;
Sec-Fetch-Site: same-origin:模拟从知乎站内访问热榜(同站请求);Sec-Fetch-Mode: navigate:模拟用户点击跳转的导航行为;Sec-Fetch-User: ?1:表示请求由用户主动触发(如点击链接),而非脚本自动发起;
- Sec-Ch-Ua 系列字段:Chrome 专属的 UA 扩展字段,提供更细粒度的浏览器版本 / 平台信息,进一步提升请求的真实性;
- Upgrade-Insecure-Requests:强制将 HTTP 请求转为 HTTPS,符合现代浏览器的安全访问习惯。
三、高级优化:构建请求头池与动态适配
3.1 请求头池的核心价值
单一固定的请求头即使再仿真,也会因 “请求特征不变” 被服务器识别(如同一 IP 下持续使用相同 UA)。构建请求头池,随机选择不同浏览器 / 设备的请求头,可大幅降低被识别的概率。
3.2 多浏览器请求头池实现
3.2.1 核心代码
python
运行
import requests
import random
from typing import Dict, List
# 构建多浏览器请求头池(Chrome/Firefox/Edge/移动端Safari)
HEADERS_POOL: List[Dict[str, str]] = [
# Chrome 120 (Windows 10)
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://www.zhihu.com/",
"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",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": '"Windows"',
},
# Firefox 121 (macOS)
{
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/121.0 Safari/537.36",
"Referer": "https://www.zhihu.com/",
"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",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-User": "?1",
},
# Edge 120 (Windows 11)
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Edg/120.0.0.0",
"Referer": "https://www.zhihu.com/",
"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",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": '"Windows"',
},
# 移动端Safari (iPhone 15)
{
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
"Referer": "https://www.zhihu.com/",
"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",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-User": "?1",
"Viewport-Width": "390",
"Mobile": "1",
}
]
def get_random_headers() -> Dict[str, str]:
"""从请求头池中随机获取一个请求头"""
return random.choice(HEADERS_POOL)
def crawler_with_headers_pool(url: str, times: int = 5):
"""使用请求头池多次请求,模拟不同浏览器访问"""
for i in range(times):
# 随机获取请求头
headers = get_random_headers()
try:
response = requests.get(
url,
headers=headers,
timeout=10,
allow_redirects=True
)
# 打印当前使用的UA和响应状态
current_ua = headers["User-Agent"].split(")")[0].split("(")[1]
print(f"第{i+1}次请求 - 浏览器特征:{current_ua} - 状态码:{response.status_code}")
except Exception as e:
print(f"第{i+1}次请求失败:{e}")
# 随机延时,模拟真人操作间隔
time.sleep(random.uniform(1, 3))
if __name__ == "__main__":
import time
target_url = "https://www.zhihu.com/hot"
crawler_with_headers_pool(target_url, times=5)
3.2.2 输出结果
plaintext
第1次请求 - 浏览器特征:Windows NT 10.0; Win64; x64 - 状态码:200
第2次请求 - 浏览器特征:Macintosh; Intel Mac OS X 14_0 - 状态码:200
第3次请求 - 浏览器特征:iPhone; CPU iPhone OS 17_0 like Mac OS X - 状态码:200
第4次请求 - 浏览器特征:Windows NT 10.0; Win64; x64 - 状态码:200
第5次请求 - 浏览器特征:Windows NT 10.0; Win64; x64 - 状态码:200
3.2.3 核心原理说明
- 多维度请求头构建:请求头池包含桌面端(Chrome/Firefox/Edge)和移动端(Safari)的请求头,覆盖不同设备 / 浏览器类型;
- 随机选择机制:通过
random.choice从池中随机选取请求头,每次请求的特征都不同; - 随机延时:结合
time.sleep(random.uniform(1, 3)),模拟真人浏览的时间间隔,进一步降低反爬风险; - 字段适配性:不同浏览器的请求头字段做差异化处理(如 Firefox 无 Sec-Ch-Ua 字段,移动端增加 Viewport-Width 字段),符合真实浏览器的特征差异。
3.3 动态生成请求头(适配最新浏览器版本)
浏览器版本持续迭代,手动维护请求头池效率低。可通过动态拼接 UA 等核心字段,适配最新版本的浏览器。
3.3.1 核心代码
python
运行
import requests
import random
def generate_latest_chrome_headers() -> dict:
"""动态生成最新版Chrome请求头(适配版本迭代)"""
# Chrome版本池(包含最新的稳定版)
chrome_versions = ["120.0.0.0", "119.0.0.0", "118.0.0.0"]
# 操作系统池
os_list = [
"Windows NT 10.0; Win64; x64",
"Windows NT 11.0; Win64; x64",
"Macintosh; Intel Mac OS X 14_1",
"X11; Linux x86_64"
]
# 随机选择版本和系统
chrome_version = random.choice(chrome_versions)
os_info = random.choice(os_list)
# 动态拼接UA
user_agent = f"Mozilla/5.0 ({os_info}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{chrome_version} Safari/537.36"
# 动态生成Sec-Ch-Ua字段(匹配Chrome版本)
sec_ch_ua = f'"Not_A Brand";v="8", "Chromium";v="{chrome_version.split(".")[0]}", "Google Chrome";v="{chrome_version.split(".")[0]}"'
# 动态生成Sec-Ch-Ua-Platform字段
if "Windows" in os_info:
sec_ch_ua_platform = '"Windows"'
elif "Macintosh" in os_info:
sec_ch_ua_platform = '"macOS"'
elif "Linux" in os_info:
sec_ch_ua_platform = '"Linux"'
else:
sec_ch_ua_platform = '"Unknown"'
# 构建完整请求头
headers = {
"User-Agent": user_agent,
"Referer": "https://www.zhihu.com/",
"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",
"Connection": "keep-alive",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
"Sec-Ch-Ua": sec_ch_ua,
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": sec_ch_ua_platform,
"Cache-Control": "max-age=0",
}
return headers
def test_dynamic_headers():
"""测试动态请求头生成"""
url = "https://www.zhihu.com/hot"
for i in range(3):
headers = generate_latest_chrome_headers()
print(f"\n第{i+1}次生成的请求头:")
print(f"UA: {headers['User-Agent']}")
print(f"Sec-Ch-Ua: {headers['Sec-Ch-Ua']}")
print(f"Sec-Ch-Ua-Platform: {headers['Sec-Ch-Ua-Platform']}")
try:
response = requests.get(url, headers=headers, timeout=10)
print(f"请求状态码:{response.status_code}")
except Exception as e:
print(f"请求失败:{e}")
if __name__ == "__main__":
test_dynamic_headers()
3.3.2 输出结果
plaintext
第1次生成的请求头:
UA: Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Sec-Ch-Ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"
Sec-Ch-Ua-Platform: "Windows"
请求状态码:200
第2次生成的请求头:
UA: Mozilla/5.0 (Macintosh; Intel Mac OS X 14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Sec-Ch-Ua: "Not_A Brand";v="8", "Chromium";v="119", "Google Chrome";v="119"
Sec-Ch-Ua-Platform: "macOS"
请求状态码:200
第3次生成的请求头:
UA: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
Sec-Ch-Ua: "Not_A Brand";v="8", "Chromium";v="118", "Google Chrome";v="118"
Sec-Ch-Ua-Platform: "Linux"
请求状态码:200
3.3.3 核心原理说明
- 版本动态适配:维护 Chrome 版本池和操作系统池,随机组合生成不同版本 / 系统的 UA,避免因版本过时被识别;
- 字段联动生成:Sec-Ch-Ua 字段的版本号与 UA 中的 Chrome 版本联动,确保字段值逻辑一致;
- 平台自适应:根据操作系统自动调整 Sec-Ch-Ua-Platform 字段值,符合真实浏览器的字段特征。
四、实战避坑指南
4.1 常见错误及解决方案
| 错误类型 | 表现形式 | 解决方案 |
|---|---|---|
| UA 字段格式错误 | 响应状态码 403,或返回异常页面 | 严格按照浏览器 UA 格式拼接,避免手动修改核心部分(如 AppleWebKit/537.36) |
| Referer 与目标域名不符 | 请求被拦截,提示 “非法来源” | 根据请求的目标 URL,设置对应的 Referer(如爬取知乎热榜,Referer 设为知乎首页) |
| Sec-Fetch-* 字段值冲突 | 响应为空或 400 错误 | 确保 Sec-Fetch-Site/Mode/Dest 的值逻辑一致(如 navigate 模式对应 document 目标) |
| 请求头字段冗余 / 缺失 | 被服务器标记为可疑请求 | 参考真实浏览器的请求头,只保留必要字段,避免添加不存在的字段(如 Firefox 添加 Sec-Ch-Ua) |
| Cookie 与请求头不匹配 | 登录态失效,返回未登录页面 | 确保 Cookie 与 UA/IP 匹配(如移动端 UA 对应移动端 Cookie) |
4.2 实战调试技巧
- 抓包对比:使用 Chrome 开发者工具(F12→Network)抓取真实请求头,与爬虫请求头逐字段对比,定位差异;
- 分步验证:先使用基础请求头测试,成功后逐步添加进阶字段,定位导致请求失败的具体字段;
- 状态码分析:
- 403:请求头被识别为爬虫,重点检查 UA、Sec-Fetch-* 字段;
- 400:请求头格式错误,检查字段值的语法(如 Sec-Ch-Ua 的引号、逗号);
- 503:服务器限流,结合 IP 代理 + 请求头池 + 延时优化;
- 日志记录:记录每次请求的请求头和响应状态,便于分析被拦截的规律。
五、扩展场景:结合 Cookie 与代理的请求头优化
5.1 Cookie 与请求头的联动
Cookie 包含用户的登录态和会话信息,与请求头结合使用可进一步提升请求的真实性:
python
运行
import requests
def crawler_with_cookie():
url = "https://www.zhihu.com/hot"
# 从浏览器抓包获取的真实Cookie(需替换为自己的)
cookie = "_zap=xxx; d_c0=xxx; _xsrf=xxx; Hm_lvt_xxx=xxx; Hm_lpvt_xxx=xxx"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://www.zhihu.com/",
"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",
"Cookie": cookie, # 添加真实Cookie
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Dest": "document",
}
response = requests.get(url, headers=headers, timeout=10)
print(f"带Cookie请求状态码:{response.status_code}")
# 验证是否获取到登录后的个性化热榜
if "个性化推荐" in response.text:
print("✅ 成功获取登录态下的热榜数据")
5.2 代理 IP 与请求头的适配
使用代理 IP 时,需确保请求头的地区特征与代理 IP 的地区匹配(如国内 IP 对应 Accept-Language: zh-CN):
python
运行
import requests
def crawler_with_proxy():
url = "https://www.zhihu.com/hot"
# 国内代理IP(需替换为有效代理)
proxies = {
"http": "http://127.0.0.1:7890",
"https": "http://127.0.0.1:7890",
}
# 适配国内IP的请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://www.zhihu.com/",
"Accept-Language": "zh-CN,zh;q=0.9", # 纯中文,适配国内IP
"Accept-Encoding": "gzip, deflate, br",
"Sec-Fetch-Site": "same-origin",
}
response = requests.get(url, headers=headers, proxies=proxies, timeout=10)
print(f"代理IP请求状态码:{response.status_code}")
总结
核心知识点回顾
- 请求头核心逻辑:HTTP 请求头的完整性、关联性、动态性是模拟真实浏览器的三大核心,缺失现代浏览器专属字段(如 Sec-Fetch-*)是爬虫被识别的主要原因;
- 基础模拟方法:精准复刻 Chrome/Firefox 等浏览器的核心字段(UA、Referer、Accept 等),可突破基础反爬机制;
- 高级优化策略:构建请求头池实现请求特征随机化,动态生成请求头适配浏览器版本迭代,结合 Cookie / 代理进一步提升请求真实性。
实战价值
自定义请求头是爬虫开发的基础且核心的进阶技巧,本文提供的请求头构建、池化、动态适配方案,可直接复用于各类网站的爬虫开发。掌握这些技巧,能够有效突破 80% 以上的基础反爬机制,大幅提升爬虫程序的稳定性和隐蔽性。在实际开发中,需结合抓包工具持续优化请求头字段,确保与真实浏览器的请求特征高度一致。

更多推荐



所有评论(0)