一、HTTP 请求头是什么
刚开始做爬虫的时候,我对 HTTP 请求头的理解就是"复制粘贴"。从浏览器开发者工具里复制一堆头部,粘贴到代码里,能跑就行。直到有一次项目出了问题,才发现不懂请求头的原理,出了问题根本不知道怎么排查。
HTTP 请求头是客户端发送给服务器的额外信息,告诉服务器"我是谁""我能接受什么""我想要什么"。理解这些头部,不仅能帮你写出更稳定的爬虫,还能在遇到反爬时快速定位问题。
每个请求头都是 Key: Value 的格式,多个头部用换行分隔。例如:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
二、常用请求头详解
2.1 User-Agent
这是最重要的请求头之一,标识了客户端的类型和版本。
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
各部分的含义:
Mozilla/5.0:历史遗留,所有浏览器都带这个Windows NT 10.0:操作系统是 Windows 10Win64; x64:64 位系统AppleWebKit/537.36:渲染引擎版本Chrome/120.0.0.0:Chrome 浏览器版本
python-requests 就直接拒绝。建议准备一个真实的浏览器 UA 列表,随机轮换使用。
2.2 Accept
告诉服务器客户端能接受什么类型的响应内容。
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
q 参数表示优先级(quality),范围是 0-1,默认是 1。数值越大优先级越高。
2.3 Accept-Language
告诉服务器客户端偏好的语言。
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
这个头部在采集多语言网站时很有用。比如同一个页面,带上 zh-CN 返回中文,带上 en-US 返回英文。
2.4 Accept-Encoding
告诉服务器客户端支持的压缩格式。
Accept-Encoding: gzip, deflate, br
支持的格式:
gzip:最常见的压缩格式deflate:另一种压缩格式br:Brotli 压缩,Google 开发的,压缩率更高identity:不压缩
2.5 Referer
告诉服务器当前请求是从哪个页面跳转过来的。
Referer: https://www.example.com/list?page=2
这个头部有两个作用:
- 防盗链:图片、视频等资源会检查 Referer,如果不是来自本站就拒绝访问
- 统计分析:网站用来看流量来源
注意:Referer 是拼写错误(正确应该是 Referrer),但 HTTP 标准就这么定了,改不了了。
2.6 Cookie
携带服务器之前设置的 Cookie 信息。
Cookie: session_id=abc123; user_id=456; last_visit=2024-01-01
多个 Cookie 用分号分隔。在爬虫开发中,Cookie 是维持登录状态的关键。
2.7 Authorization
用于身份验证。
# Bearer Token(JWT 等)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# Basic 认证
Authorization: Basic YWRtaW46MTIzNDU2
# API Key
Authorization: ApiKey your_api_key_here
2.8 Content-Type
告诉服务器请求体的数据格式。
# 表单数据
Content-Type: application/x-www-form-urlencoded
# JSON 数据
Content-Type: application/json
# multipart 表单(文件上传)
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
# 纯文本
Content-Type: text/plain
三、安全相关头部
3.1 X-Forwarded-For
用于标识客户端的真实 IP,通常在代理服务器中使用。
X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178
这个头部在爬虫开发中有个特殊用途:有些网站会根据 IP 限制访问,你可以尝试修改这个头部来绕过限制(但不保证有效)。
3.2 X-Requested-With
标识请求是否来自 AJAX。
X-Requested-With: XMLHttpRequest
很多网站的后端接口会检查这个头部,如果不是 XMLHttpRequest 就拒绝服务。
3.3 Origin
标识请求的来源域名,用于 CORS 安全控制。
Origin: https://www.example.com
四、跨域相关头部
4.1 简单请求 vs 预检请求
跨域请求分为两种情况:
- 简单请求:GET、POST、HEAD 方法,且头部在允许范围内
- 预检请求:先发送 OPTIONS 请求询问服务器是否允许
4.2 Access-Control-Request-Headers
预检请求中,告诉服务器实际请求会带哪些头部。
Access-Control-Request-Headers: content-type,authorization
4.3 Access-Control-Request-Method
预检请求中,告诉服务器实际请求会用什么方法。
Access-Control-Request-Method: POST
五、缓存相关头部
5.1 Cache-Control
控制缓存行为。
# 客户端告诉服务器:不要给我缓存的内容
Cache-Control: no-cache
# 客户端告诉服务器:我可以接受最长 60 秒的缓存内容
Cache-Control: max-age=60
5.2 If-None-Match
配合 ETag 使用,用于条件请求。
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
如果服务器资源的 ETag 没有变化,就返回 304 Not Modified,不返回实际内容。
5.3 If-Modified-Since
配合 Last-Modified 使用,也是条件请求。
If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
六、爬虫开发中的头部技巧
6.1 构造完整的请求头
import requests
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',
'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',
'Referer': 'https://www.example.com',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
response = requests.get('https://www.example.com', headers=headers)
6.2 模拟 AJAX 请求
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest',
'Referer': 'https://www.example.com/page',
}
response = requests.get('https://api.example.com/data', headers=headers)
6.3 处理特殊的头部
有些网站会检查一些不常见的头部,比如:
# 抖音的验证头部
headers = {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X)...',
'Referer': 'https://www.douyin.com/',
# 抖音特有的头部
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
'sec-ch-ua-mobile': '?1',
'sec-ch-ua-platform': '"iOS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
}
七、总结
HTTP 请求头看似简单,但里面的门道很多。做爬虫开发,不能只停留在"复制粘贴"的层面,理解每个头部的作用,才能在遇到问题时快速定位。
| 头部 | 作用 | 爬虫场景 |
|---|---|---|
| User-Agent | 标识客户端 | 必带,模拟浏览器 |
| Accept | 接受的内容类型 | 请求 JSON 时设为 application/json |
| Referer | 来源页面 | 防盗链、反爬检查 |
| Cookie | 会话状态 | 维持登录状态 |
| Authorization | 身份验证 | API 认证 |
| X-Requested-With | AJAX 标识 | 模拟异步请求 |
记住:请求头不是越多越好,而是越"真实"越好。模拟一个真实浏览器的请求头,比堆砌一堆无关的头部更有效。