爬虫的底层动作是"发 HTTP 请求拿资源"。但请求是抽象的------你看不到它到底发了什么、服务器回了什么。F12 的 Network 面板,就是浏览器帮你把这些看不见请求一条条摊开给你看的"监控屏"。
打开一个网页,其实发生了几十次请求
你以为是"访问一个网址 = 一次请求",其实浏览器会发一大串:
| 资源类型 | 说明 |
|---|---|
| 主 HTML | 页面的骨架文档 |
| CSS | 样式 |
| JavaScript | 脚本 |
| 图片 | 图片资源 |
| JSON API | 动态数据接口(这个是你最该盯的) |
| 字体 / 其他 | 字体、图标、埋点等 |
Network 面板里每一行就是其中一个请求。你要做的,是从这一大堆里挑出那个返回目标数据的请求。
每个请求里,你要会看这几项
点开一条请求,右侧能看到的东西,正好对应爬虫需要理解的全部内容:
表格
| 面板项 | 含义 | 爬虫为什么关心 |
|---|---|---|
| Request URL | 请求地址 | 你要用 requests 请求的就是它 |
| Request Method | GET / POST | 决定你代码用 get 还是 post |
| Status Code | 200 / 403 / 500 | 判断请求成没成功 |
| Request Headers | UA、Cookie、Referer 等 | 反爬常卡在这里,要复制伪装 |
| Query Parameters | URL 上的参数 | 分页参数 page 就在这 |
| Request Payload | POST 提交的表单 / JSON | POST 接口的入参在这 |
| Response / Preview | 服务器返回的内容 | 判断返回的是 HTML 还是 JSON |
一个关键认知:数据不一定在 HTML 里
当你在地址栏敲下 https://xxx.com/news 并回车,浏览器和服务器之间完成了一次 HTTP 请求与响应的对话------浏览器说"我要这个页面",服务器回一份东西,就这么简单。但这份"东西"里到底装着什么,决定了两条完全不同的路。
你看到页面:
----------------
台湾娱乐新闻
周杰伦演唱会消息
某明星新剧开播
某艺人采访
----------------
第一条路是传统的服务端渲染。服务器把新闻标题、时间、摘要统统拼进一段完整的 HTML 里返回,<h2>周杰伦演唱会消息</h2>、<h2>某明星新剧开播</h2> 明明白白写在源码中。这种情况下,爬虫的工作异常轻松:requests.get() 拿到 HTML,BeautifulSoup 或 lxml 解析一下,数据就出来了,一步到位。
第二条路是如今更主流的前后端分离。同样访问 /news,服务器返回的 HTML 却是个"空壳"------翻遍源码也找不到任何一条新闻,只有一个空荡荡的 <div id="root"></div> 和一句 <script src="app.js">。新闻根本不在这里。真正的数据,藏在浏览器随后执行的那段 JavaScript 里。app.js 会在后台悄悄发起第二个请求,比如 GET https://xxx.com/api/news?page=2,向服务器索要"第 2 页新闻";服务器则回一包结构清晰的 JSON:{"items": {"title": "周杰伦演唱会消息", "time": "2026-10-14"}, ...}。浏览器拿到这包 JSON,再由 JS 把内容动态填进那个空盒子里,你这才在屏幕上看到了新闻。
换句话说,你在 F12 的 Network 面板里看到的那条 GET /api/news?page=2,正是浏览器替你做的一次"取数"动作,而它对应的 Response,就是那包货真价实的数据。页面只是数据的展示层,数据本身来自另一个独立的 HTTP 请求。
这恰恰是爬虫最钟爱的入口。走 HTML 那条路,你得先解析一层层嵌套的 DOM,再清洗掉冗余标签,才能在 <div class="xxx">标题</div> 里刨出那句标题;而走 API 这条路,数据早已被后端整理成规整的 JSON,title 对应标题、time 对应时间,json.loads() 一转换直接就能用,省掉了繁琐的解析与清洗。所以一条铁律值得刻在脑子里:接口优先于硬解析页面。
于是,面对一个新网站,正确的起手式不是找选择器,而是判断数据落在哪儿。它通常只有三种归宿:如果数据直接写在 HTML 里,那就老老实实用 CSS 或 XPath 解析;如果数据躲在某个 JSON 接口里,那就定位接口、直接构造请求拿数据;如果数据是前端 JS 现场计算、拼接出来的,那就去逆推它的接口,或者干脆上浏览器自动化,让它替你把页面渲染完整再取。
现阶段只看这几个标签就够
别被 F12 一堆面板吓到,你现在只需要盯这 5 个:
-
Network:看网页实际发了哪些请求。
-
Headers:看 URL、GET/POST、Cookie、User-Agent。
-
Payload:POST 请求提交了什么数据,重点看。
-
Response / Preview:服务器到底返回 HTML 还是 JSON。
-
Fetch/XHR 筛选 :最重要------动态网页的数据接口几乎都藏在这里,点一下就能把图片、CSS 这些噪音过滤掉,只剩数据请求。
把它练成一个固定动作
接口分析说白了就是一套肌肉记忆,建议你每次都按这个顺序走:
打开网页
→ F12
→ 切到 Network
→ 刷新页面(不刷新,之前的请求会被清空看不到)
→ 点 Fetch/XHR 筛掉噪音
→ 找那个返回 JSON 的请求
→ 看 Request URL(这就是要打的接口)
→ 看 Params / Payload(这就是要传的参数)
→ 看 Response(确认数据在里面)
走完这一遍,一个"看起来只能靠浏览器渲染"的动态网页,在你眼里就变成了"一个可以直接用 requests 打的接口 + 一堆参数"------这就是接口分析的第一步,也是爬虫从"解析 HTML"进阶到"直接拿数据"的分水岭。
Network
记录的是原始 HTTP 报文 的交换过程。 它是浏览器发起请求和接收响应的流水账。它关注的是 Request Header、Status Code、Response Body(通常是原始的 JSON 或 HTML 字符串)。
1) Request Headers (请求头)
请求头是客户端告诉服务器"我是谁"以及"我想要什么"的信使。对于爬虫而言,它最核心的作用是绕过反爬机制 和传递关键凭证。
-
User-Agent (UA):最常见的反爬防御。服务器通过 UA 来判断请求来自浏览器还是 Python 脚本。爬虫必须伪装 UA,否则会直接收到 403 错误。
-
Cookie / Authorization:携带用户的登录状态或身份令牌。没有正确的 Cookie,服务器会拒绝返回数据。
-
Referer:防盗链机制。很多资源文件(如图片、视频)会校验 Referer,确保请求是从特定页面发出的,而不是被其他网站或脚本直接调用。
-
Content-Type / Accept:告诉服务器你发送的数据格式(如 JSON、表单数据)以及你期望接收的数据格式。
2) Response Body (响应体)
响应体是服务器返回的实际内容。在爬虫中,它是最终要解析和提取的目标。
-
HTML 结构:静态网页的响应体就是完整的 HTML 源码,爬虫通过 XPath 或 CSS 选择器从中提取数据。
-
JSON 数据 :API 接口的响应体通常是纯文本格式的 JSON 字符串,爬虫直接通过
json.loads()将其转换为字典或列表进行结构化提取。 -
二进制流 :下载图片或视频时,响应体是二进制数据,需要以
wb模式写入本地文件。 -
无用的外壳:在某些动态渲染严重的网页中,HTML 格式的响应体可能只是一个空骨架,此时它对于数据提取毫无价值,必须去 Network 里寻找 API 的 JSON 响应体。
3)Status Code (状态码)
-
200 :请求成功,开始解析
Response Body。 -
301 / 302 :重定向。爬虫需要捕获
Location头,进行重定向跟踪,否则拿到的页面是错的。 -
304 :未修改(如你之前遇到的)。需要禁用缓存,或者在请求头中删除
If-Modified-Since等字段,强制获取最新数据。 -
403 / 429:禁止访问 / 请求过多。典型的反爬触发信号,说明你的 Headers 没伪装好,或者触发频率限制,需要降速或更换代理 IP。
Elements (DOM)
记录的是浏览器解析并渲染后的内存对象树。 它是浏览器接收 HTML 字符串后,根据 W3C 规范进行词法分析、构建 DOM 树、执行 JavaScript(可能动态修改 DOM)、加载 CSS 后的最终状态。
Preview 标签的作用
它是 F12 为了方便开发者快速识别响应体类型而提供的格式化预览功能。
-
如果响应头
Content-Type是application/json,Preview 会自动将原始字符串解析为树状折叠的 JSON 对象,让你能像看文件夹一样展开查看 key-value 对。 -
如果响应是图片,它会渲染出图片缩略图。
-
如果是 HTML,它会展示 HTML 的 DOM 树结构。