HTTP 请求头完全指南

每个头部的含义、用法和爬虫开发中的实际应用

一、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 10
  • Win64; x64:64 位系统
  • AppleWebKit/537.36:渲染引擎版本
  • Chrome/120.0.0.0:Chrome 浏览器版本
爬虫技巧:很多网站会检查 User-Agent,如果看到 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:不压缩
性能优化:开启压缩能大幅减少传输数据量。Requests 库默认会自动处理 gzip 解压,不需要额外配置。

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', }
快速获取头部:用浏览器访问目标网站,在开发者工具里找到请求,右键复制为 curl,然后用 curl 转 Python 工具 转换,所有头部都会自动带上。

七、总结

HTTP 请求头看似简单,但里面的门道很多。做爬虫开发,不能只停留在"复制粘贴"的层面,理解每个头部的作用,才能在遇到问题时快速定位。

头部 作用 爬虫场景
User-Agent 标识客户端 必带,模拟浏览器
Accept 接受的内容类型 请求 JSON 时设为 application/json
Referer 来源页面 防盗链、反爬检查
Cookie 会话状态 维持登录状态
Authorization 身份验证 API 认证
X-Requested-With AJAX 标识 模拟异步请求

记住:请求头不是越多越好,而是越"真实"越好。模拟一个真实浏览器的请求头,比堆砌一堆无关的头部更有效。