网页抓取 vs API:如何使用 Python 提取 JSON 数据

如果网站本身就通过 JSON 接口加载数据,那么直接调用该接口通常比抓取 HTML 或运行 Selenium 更快。您可以直接从页面所用的数据源获取结构化数据,无需等待浏览器渲染每一个按钮、卡片、脚本、图片和弹窗。
HTML 抓取和浏览器抓取依然有其用武之地。有些网站会把数据直接放在页面源码里,另一些则需要点击、滚动、填写表单,或者需要一个能渲染页面的浏览器。但在许多动态网站上,最干净的路径要从浏览器的 Network(网络)面板开始。
现代网页给了抓取者尽早检查这条路径的理由。 HTTP Archive Web Almanac JavaScript 章节 的报告显示,JavaScript 传输量的中位数在 移动端达到 558 KB 和 桌面端达到 613 KB (2024 年数据)。如今许多页面先加载 HTML 外壳,再通过后台请求获取真正的数据。
举个例子,假设您要抓取一个酒店预订引擎。传统的 HTML 方法只会返回空的容器。Selenium 虽然能渲染出房型,但每个页面都很慢,翻页时还会报错。如果房价、日期、房型名称和可订状态都来自一个后台 JSON 请求,您就可以直接从该接口采集这些数据。
本指南将演示如何检查页面、找到 API 请求、在 Postman 中测试、转换为 Python 代码、处理分页,并把结果保存为 CSV。
快速结论:该用网页抓取还是 API?
使用 API 抓取 适用于页面通过 Fetch/XHR 加载干净 JSON、且该接口可以安全请求的情况。
试试 HTML 抓取 适用于数据已经存在于页面源码中的情况。
使用 浏览器抓取 适用于工作流需要 JavaScript 渲染、点击、滚动、截图、表单提交或可视化调试的情况。
在 DevTools 中能看到某个前端接口,并不等于自动获得了大规模复用它的许可。在构建大型抓取程序之前,请先查看网站的条款、访问规则,以及是否存在官方 API。
网页抓取与 API:有什么区别?
网络爬虫 是从网站页面中提取数据。而 API 抓取是向网站用来加载结构化数据的接口发送请求,返回的通常是 JSON。
| 方法 | 工作原理 | 最佳起点 |
| HTML 抓取 | 下载页面 HTML 并解析元素 | 静态页面 |
| 浏览器抓取 | 用 Selenium 或 Playwright 打开页面 | JavaScript 密集型页面、点击、滚动 |
| API 接口抓取 | 直接调用后台的 JSON 请求 | 带可见 XHR/fetch 数据的动态页面 |
在一个基本的 网络爬虫 工作流中,抓取程序会下载 HTML 并通过选择器提取文本。NodeMaven 的 Python 网页抓取 指南介绍了使用 Requests 和 BeautifulSoup 的这种传统方法。
API 接口抓取的原理不同。浏览器加载页面,JavaScript 向服务器请求数据,服务器返回 JSON。您的 Python 脚本不去抓取渲染出来的卡片或表格,而是发送一个类似的请求并读取 JSON 响应。
这正是 API 抓取更快、更干净的原因。在网站把数据变成可视化元素之前,它本来就已经是结构化的。
官方 API 与前端接口
官方 API 有文档,专为开发者打造。它通常具备身份验证、速率限制、版本管理、响应示例和使用规则。
前端接口是网站自身界面在后台发送的请求。您通常可以在 Chrome DevTools 的 Fetch/XHR 中看到它。它可能返回干净的 JSON,但也可能在毫无预告的情况下变更,并且可能依赖 cookie、令牌、请求头或签名载荷。
当官方 API 能提供您需要的字段和额度时,就使用官方 API。只有在允许访问、且请求能被稳定复现时,才使用前端接口。当接口过于难以复现,或工作流依赖渲染后的页面时,就使用浏览器抓取。
为什么抓取 API 接口比用 Selenium 更快
酒店预订引擎可能要等 JavaScript 从 API 加载价格和可订状态之后,才会显示房型卡片。Selenium 可以等待卡片渲染完成,但每次运行都会带来 浏览器启动、JavaScript 执行、图片、CSS、弹窗以及等待逻辑.
当同样的数据已经以 JSON 形式提供时,API 端点抓取会跳过渲染出来的界面。您的脚本无需等待浏览器显示房间卡片,而是直接请求 其背后的数据.
这一点在开发者讨论中经常出现。在一个 关于 Selenium 抓取速度慢的 Stack Overflow 讨论帖中,答案指出问题在于 Selenium 的浏览器开销,并建议查看 Network 面板,用 Python 复现底层请求。
这种做法可以减少:
- 为每个字段编写冗长的 CSS 选择器
- 等待元素渲染完成
- 浏览器崩溃
- 翻页缓慢
- 杂乱的 HTML 解析
- 高 CPU 与内存占用
但 API 端点抓取并非总是正确的选择。有些端点需要 私有授权、CSRF 值、一次性令牌、签名载荷或严格的会话校验。还有一些端点会毫无预警地变动,因为它们是为网站前端设计的,而不是给外部开发者使用的。
如果端点受到限制,或者工作流程需要 点击、截图、滚动、表单或可视化调试,那就改用浏览器抓取。 Playwright 和 Selenium 两者都会打开页面、运行 JavaScript,并处理渲染后的结果。
如果基于浏览器的抓取需要 云端执行、代理、CAPTCHA 支持、Live Browser 调试以及会话录制, NodeMaven 抓取浏览器 为您提供托管的 Chrome 环境,无需自行维护整套浏览器栈。
如果网站提供了官方 API,且包含您需要的字段和额度,那就从它开始。它 有文档、有版本管理,通常也更易于维护 而不是在 DevTools 中找到的前端端点。
教程准备:工具与演示网站
本教程需要准备以下四样东西:
- Chrome
- Postman
- Python 3
- Requests 库
本演示使用 Quotes to Scrape 无限滚动页面。它专为抓取练习而设计,数据动态加载,并提供了一个清晰的 JSON 端点。
在运行 Python 示例之前,您需要在虚拟环境中安装 Requests。这样可以避免在较新版本的 Homebrew Python 上可能出现的 externally-managed-environment 错误。
第 1 步:在 Chrome DevTools 中找到 API 接口
打开 Quotes to Scrape 无限滚动页面 在 Chrome 中。
右键点击页面并选择 检查。打开 网络 标签页,然后点击 Fetch/XHR。重新加载页面或向下滚动,直到出现新的请求。
在请求列表中,点击 quotes?page=1。然后打开 Preview 标签页。如果您看到 has_next、page、quotes 和 top_ten_tags 等字段,说明您已经找到了页面背后的 JSON 响应。
在本演示中,该端点为:
其中 page=1 部分用于控制分页。稍后,Python 脚本会更改该值,以采集第 2 页、第 3 页以及其余可用结果。
Chrome 的 Network 功能参考文档 说明了 Network 面板如何展示页面发出的请求,包括 Fetch/XHR 请求和响应预览。

第 2 步:在 Postman 中测试接口
在 Chrome DevTools 中找到该请求后,右键点击 quotes?page=1 并选择:
Copy > Copy as cURL
打开 Postman,把复制的 cURL 粘贴到请求 URL 字段中。在本演示中,Postman 会提取出端点并显示为:
保持请求方法为 GET,然后点击 发送.
如果响应面板显示 200 OK 以及 has_next、page 和 quotes 等 JSON 字段,说明该端点在浏览器之外也能正常工作。
同时检查 Params 选项卡。Postman 会将 page=1 拆分为一个查询参数。这一点很重要,因为 Python 脚本稍后会将该值改为 page=2、page=3,依此类推。
现在打开 Postman 的 代码片段 面板并选择 Python – Requests。Postman 会为同一请求生成 Python 代码,包括端点 URL、方法、请求头和负载结构。
对于真实网站,请把这段生成的代码作为起点。请求头、cookies、令牌和负载值可能直接决定该端点在浏览器之外能否正常工作。

转入 Python 前需要检查什么
在编写代码之前,请先在 Postman 中检查该请求。
尽可能优先从 Request URL。这是端点地址。然后检查 方法,通常是 GET 或 POST。
GET 请求通常把参数值放在 URL 中,POST 请求则可能发送单独的负载。
接下来,检查 查询参数。在本演示中,page=1 用于控制分页。在真实网站上,参数可以控制搜索词、类别、城市、日期、货币、排序方式、偏移量或游标。
对于 POST 请求,请打开 Payload 标签页。订房网站可能会发送 destination、checkin、checkout、adults、currency 和 page 等参数值。电商端点则可能使用 query、category、sort、limit 和 offset。
转入 Python 之前,请检查:
- Headers: content type、accept、user agent 以及请求特有的请求头
- Cookies 或令牌: 会话值、CSRF 令牌或授权凭证值
- 响应结构: 您需要的字段在 JSON 中的位置
- 分页字段: 例如 page、offset、cursor、has_next 或 next 等值
如果之后 Python 请求失败,通常就是漏掉了其中某一项。
第 3 步:编写并运行第一个 Python 请求
打开代码编辑器,例如 VS Code、Cursor,或纯文本模式下的 TextEdit。
新建一个文件,命名为:
粘贴 Python – Requests 由 Postman 生成的代码粘贴到该文件中:
保存文件。
打开终端并进入您保存该文件的文件夹。例如,如果您把它保存在桌面上,请运行:
创建一个虚拟环境:
激活它:
在虚拟环境中安装 Requests:
运行脚本:
如果一切正常,终端会打印出 JSON 响应。
在这一阶段,目标很简单: 确认 Python 能够发送您在 Postman 中测试过的同一个请求.
如果您看到提示找不到文件的报错,请检查文件名。在 Mac 上,TextEdit 可能会把文件保存为 .rtf 格式。
第 4 步:采集所有分页并保存为 CSV
Go back to quotes_api_scraper.py.
现在,用一个完整的爬虫替换测试代码。这个版本会沿用 Postman 中的相同请求头,自动更改 page 的值,并将结果保存到 quotes.csv。
保存文件并再次运行:
现在您应该会在同一个文件夹中看到一个新文件:
quotes.csv

这个 CSV 就是本教程的最终成果。它包含所有可用页面中的语录内容、作者姓名和标签。
在真实网站上,一开始请保留 Postman 生成的请求头。等抓取脚本跑通之后,您可以逐个删除可选的请求头并重新测试。
为什么 API 抓取需要代理、稳定会话或地理定位
API 端点抓取比浏览器自动化更快,但 请求仍然来自某个 IP 地址。在小规模场景下,您的普通网络连接可能就够用。规模变大后,反复请求端点可能会遇到 速率限制、区域化响应或 IP 信誉检查.
对于跨大量页面的独立端点请求, 轮换住宅代理 有助于把流量分散到 干净的家庭用户 IP 上。对于预订引擎、本地商户列表或价格监控, 粘性会话 有助于在任务执行期间保持请求环境的一致性。
使用 ISP 代理 适用于 从一个稳定 IP 进行的周期性监控。对于 Python 脚本,NodeMaven 的 适用于 Python 的代理 页面介绍了常见的配置方式。如果该端点返回本地价格、配送可用性或区域性商品列表, ZIP 级别定位 有助于将数据集与目标位置对应起来。
对于预订类端点, 价格、税费、可用性和货币 可能会因国家、城市、cookie 和会话状态而变化。如果抓取程序在请求之间切换了地区,即使代码运行正常,CSV 数据也可能出现前后不一致。
抓取 API 接口时的常见问题
端点在 Chrome 中可用,但在 Python 中失败
这通常意味着 Python 请求缺少了浏览器自动发送的某些内容。
请检查请求头、cookie、CSRF 令牌、授权值、签名请求字段以及 POST 载荷。将 DevTools 中可正常工作的请求与 Python 请求逐项对比。
A 关于抓取动态网页表格的 Stack Overflow 讨论帖 清楚地展示了这种模式。XHR 请求需要先从页面获取验证令牌,API 请求才能成功。
API 返回 401、403 或 429
401 或 403 通常意味着该端点需要授权、有效会话或请求签名。请勿强行访问私有端点。
429 表示请求过多。请放慢速度、添加带退避机制的重试,并避免所有请求都从同一个 IP 发出。对于规模较大的公开数据采集任务, 轮换住宅代理 可以将请求分散到更干净的家庭宽带 IP 上,而 ISP 代理 更适合需要固定地址的周期性检查。
JSON 为空或缺少字段
该请求可能需要日期、地区、搜索关键词、页码、筛选条件、货币或载荷值。
打开 Payload 和 Query String Parameters DevTools 中的相关标签页。然后修改其中一个值,在 Postman 中重新发送请求。这有助于您弄清哪个参数控制响应中的哪部分内容。
端点发生变更
前端端点并不是稳定的接口约定。网站可能在毫无预告的情况下重命名路由、更改载荷、移除字段或新增令牌校验。
在保存数据前先做响应校验。如果缺少必需字段,请记录 URL、状态码、响应片段和时间戳,而不是把错误数据写入 CSV。
如果该端点依赖点击操作、渲染后的内容、私有令牌或持续的浏览器状态,请改回浏览器抓取方式。对于这类情况, NodeMaven 抓取浏览器 可以运行真实的云端浏览器,并支持 NodeMaven 代理、CAPTCHA 处理、Live Browser 调试和会话录制。
结论
在动手编写 Selenium 抓取程序之前,先查看 Network 标签页。如果页面本身就通过 JSON 端点加载数据,采用 API 抓取可以节省时间并获得更整洁的输出。
先从一个请求开始。在 Postman 中测试它,把它转换成 Python 代码,加上分页,再把数据保存为 CSV。然后在扩大任务规模之前,检查速率限制、地区、cookie、会话行为以及代理质量。
做小规模测试时,用您自己的网络连接通常就够了。但如果要反复进行 API 抓取,或者采集本地价格、预订结果、商品库存,又或者在云端运行 Python 任务, 纯净的代理 和稳定的会话可以避免一个本来正常的脚本抓回一堆脏数据。



