别再只背概念了,打开Chrome F12,手把手拆解一个真实HTTP请求报文

40 阅读5分钟

摘要:上篇我们搞懂了HTTP协议的基本对话规则,知道了爬虫的核心就是模拟浏览器发请求。但一个完整的HTTP请求到底长什么样?本篇不再停留在理论,直接用Chrome开发者工具,带你亲眼看到一个真实请求的每一行,并告诉你爬虫该重点关注哪里。

前情回顾[:](爬虫敲门砖|5分钟拆解HTTP协议:原来你的第一个“爬虫”早已是浏览器。 - 掘金)

一、把请求“抓”出来:跟着我做

理论听再多,不如亲眼看一下。现在就打开你的 Chrome 浏览器,跟着操作:

image.png

按 F12 打开开发者工具。

点击顶部的 Network(网络) 面板。

在地址栏输入 www.example.com 并回车。

页面加载后,Network 面板会出现一系列请求。找到第一个名为 example.com 的请求,点击它。

右侧弹出的详情,就是我们今天要彻底拆解的“一次真实 HTTP 请求”的真身。

先瞥一眼 Headers 标签下的“常规”信息,很快扫过就好:

image.png

请求网址:www.example.com/

请求方法:GET

状态代码:200 OK

远程地址:104.20.23.154:443

这一步,你已经亲眼看到了一个 HTTP 请求的“全身照”。接下来我们逐一放大。

二、请求行:HTTP/2 的“伪标头”其实就是它

在 HTTP/1.1 中,请求行是纯文本的第一行,比如 GET / HTTP/1.1。但由于我们现在走的是 HTTPS + HTTP/2,Chrome 把请求行拆成了几个带冒号的“伪标头”,放在了请求头的顶部。

你会看到:

image.png

:method: GET

:path: /

:authority: www.example.com

把它们拼回我们熟悉的样子,就是:

http GET / HTTP/1.1 Host: www.example.com 这和上篇讲的请求行+Host头完全一致。协议虽然升级了,但它回答的三个核心问题没变:

我要干什么?(GET ——获取数据)

我要访问哪个路径?(/ ——根目录)

我要访问哪台主机?(www.example.com)

一句话:用 GET 方法,向 www.example.com 这台服务器要根目录下的内容。

三、请求头:爬虫伪装的重中之重

请求行下面那一堆 名称: 值 就是请求头。它们才是写爬虫时你最需要理解、最需要精心伪造的部分。 我把截图里的那些头分成几类,逐一拆解,并告诉你要怎么在爬虫里处理。

  1. 基础能力类

:scheme: https 协议方案,告诉服务器用 HTTP 还是 HTTPS。用 requests 库时你无需操心,它会根据 URL 自动处理。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,... 浏览器告诉服务器:“我能接收这些格式”。q=0.9 是优先级权重,大意是“我最想要 HTML,XML 和图片也能凑合收”。

🕷️ 爬虫建议:如果你只关心 HTML,可以简化为 text/html, /,减少无关传输。

Accept-Encoding: gzip, deflate, br, zstd 告诉服务器“我支持这些压缩算法,请压缩后传给我”。

🕷️ 新手常踩的坑:requests 默认不会自动解压 br(Brotli)编码,可能导致你拿到的是一堆乱码。后续我们会专门讲如何处理。

Accept-Language: zh-CN,zh;q=0.9 要求服务器优先返回中文内容。

🕷️ 如果你需要获取英文原始数据,记得把这个头改成 en-US,否则某些国际站会自动给你翻译后的页面。

  1. 爬虫伪装最核心:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ... Chrome/147.0.0.0 Safari/537.36 这是你整个请求的“身份证”。它告诉服务器:我是一个运行在 Win10 x64 上的 Chrome 147 浏览器。

🕷️ 必须记住:如果你直接用 Python 的 requests 库发请求,这里的字符串会是 python-requests/2.x.x,等于举着“我是爬虫”的牌子。我们的第一篇实战就会教你如何把它伪装成上面这串复杂的真实浏览器 UA。

  1. 安全策略与身份类 Sec-Ch-Ua、Sec-Ch-Ua-Mobile、Sec-Ch-Ua-Platform 这是 Chrome 的“用户代理客户端提示”,可以视为 User-Agent 的补充包,提供更详细的浏览器和系统信息。高级反爬系统可能会验证它们的一致性。

Sec-Fetch-Site: none 说明这次请求是直接通过地址栏输入的,不是从哪个页面跳转过来的。

none:直接访问

same-origin:同站跳转

cross-site:跨站跳转 一些严格的反爬机制会校验这个头的值是否合理。

Upgrade-Insecure-Requests: 1 表示客户端愿意把不安全的 HTTP 请求升级为 HTTPS。基本每次都会出现,知道即可。

Cache-Control: no-cache / Pragma: no-cache 告诉沿途代理和服务器:“不要给我缓存,我要最新的数据”。这对爬虫来说通常正是我们想要的效果。

  1. 其他可忽略项 Priority: u=0, i HTTP/2 的优先级标识,写爬虫时可以直接省略,不必纠结。

四、请求体:为什么这次你看不到

在整个请求详情里,你完全找不到“请求体”的影子。这是对的,因为这是一个 GET 请求。

GET 请求的所有参数都拼接在 URL 上(虽然这次没有额外参数),所以没有请求体。请求体是 POST 的专属区域,我们到登录实战那一讲再专门拆解。

五、从看图到写码:你已站在实战门口

现在,让我们回到刚才那个 Network 面板。从头到尾再看一遍这个请求,是不是每一行的含义都变得非常清晰了?

它实际上就做了一件事: 一个名叫 Chrome 的浏览器,向 www.example.com 的根目录,索要一份 HTML 网页,并希望得到中文、压缩过的格式。

而我们接下来要学的全部爬虫技能,本质就是: 用 Python 代码,把这个跟浏览器一模一样的请求“捏”出来,发给服务器,然后把它返回的 HTML 拿到手,解析出有价值的数据。

当你能够熟练地认出每一个头的作用,知道哪些需要留、哪些可以删、哪些必须改,你就已经拿到了控制 HTTP 请求的钥匙。

如果这篇文章帮你把请求报文看透了,欢迎点赞收藏,任何关于请求头构造的疑问,评论区见。