← 返回博客

网站隐藏的JSON API:如何找到内部端点并减少爬虫流量

网站自动以 JSON 格式返回数据——这个响应比 HTML 页面轻十倍。我们逐步分析如何在 DevTools 中找到内部端点,为什么复制的 cURL 可以工作而您的代码不行,如何处理令牌和分页,以及何时最好放弃这个想法。

📅2026年9月22日
网站隐藏的JSON API:如何找到内部端点并减少爬虫流量

解析器提取400 KB的HTML,只为了八个字段,而网站自己在8 KB的JSON响应中返回这些字段。差异达到五十倍——这不是关于“优雅代码”,而是关于居民代理的账单,您为每个千兆字节付费。我们来探讨如何找到网站的内部API,2026年时阻碍其重现的因素,以及何时应放弃这个想法。

如果HTML已经被解析,为什么还要寻找隐藏的API

几乎所有现代界面——React、Vue、Angular、Next.js——首先加载页面框架,然后通过对自己的端点发出单独请求来获取数据。这些端点没有文档,但它们确实存在,响应为纯JSON,并且无需无头浏览器即可访问。

转到这些端点后,您将获得:

  • 流量减少一个数量级。在解析典型商品搜索结果时,HTML页面的大小约为400 KB,包括标记、样式和跟踪器,而相应的JSON端点约为8 KB,并且其中的字段更多:内部ID、库存、商品选项。
  • 不需要浏览器。渲染JavaScript的过程消失了,随之而来的是内存、处理器和数十个额外请求(用于字体和分析)。
  • 数据已经结构化。没有因CSS类变化而崩溃的选择器。
  • 请求更少——被封禁的机会更少。在浏览器中渲染一个目录页面需要数十次对网站的请求;通过API获取相同的数据只需一次。

对于使用居民代理的项目来说,这直接节省了开支:费用按千兆字节计算,从渲染转向JSON通常会比任何图像屏蔽的技巧更大幅度地减少账单。相关主题——如何通过其他方法将解析器流量减少5倍。

逐步:如何找到端点

  1. 首先检查是否有官方API。查看目标网站的/developers、/api、/docs。公开的文档化API会有版本控制并警告弃用,而私有API则默默变化。
  2. 打开开发者工具(F12),并转到网络选项卡,确保记录已开启。
  3. 启用Fetch/XHR过滤器。它会过滤掉图片、字体和分析,只保留数据请求。
  4. 清除列表,以去除初始加载的噪音。
  5. 触发所需数据:滚动搜索结果,点击“下一页”,应用过滤器,打开商品卡片。您感兴趣的请求会在操作时出现。
  6. 找到包含您数据的响应。最快的方法是按Ctrl+F在网络面板中搜索:寻找您在屏幕上看到的唯一值(商品编号、确切价格、名称的一部分),查看哪个请求产生了它。
  7. 完整复制请求:右键单击行→复制→复制为cURL。然后通过curlconverter转换为代码,这样您就不会丢失任何头信息。

值得优先关注的典型路径:/api/、/v1/、/v2/、/search、/products、/listings、/graphql。

特殊情况:Next.js网站

在这里,数据通常根本不需要单独请求——它们直接在HTML中。旧的页面路由器中是__NEXT_DATA__块。在应用路由器(Next.js 13及更新版本)中,水合数据分散在多个script节点中的self.__next_f.push()调用中——这是序列化的React服务器组件的有效负载。手动解析它并不愉快:块通过$前缀相互引用,并且可能在字符串中间被切割。Python有一个名为nextflight的库,可以解析HTML中的Flight有效负载和原始RSC响应(带有RSC: 1头的请求),并建议根据键名而不是数组索引进行搜索——这样解析器可以在网站重新部署时生存下来。

参数反向解析:分页和过滤器

找到的端点几乎总是带参数的。常见的三种模式:

  • 按页:?page=3&per_page=20
  • 偏移和限制:?offset=40&limit=20
  • 光标:?after=<token>&limit=20——下一页的token在前一个响应的主体中返回

节省调试时间的三条规则:

  • 停留在空包上,而不是预先计算的页数:在私有API中,total计数器往往不可靠。
  • 检查实际包的大小。请求了100,返回了20——这意味着端点有自己的上限,您的分页计算已经不正确。
  • 不要访问第500页。深度分页几乎在所有地方都被服务器截断;相反,使用过滤器按类别、价格范围或日期来切割选择。

为什么浏览器中的cURL有效,而您的代码无效

这是最常见的失败点,原因几乎总是一个:丢失的头信息。复制的cURL包含请求的所有上下文,而自定义客户端则没有。

通常被认为是必需的:

  • 带有X-前缀的自定义头信息——X-CSRF-Token、X-Requested-With: XMLHttpRequest以及各种X-*-Token,这些都是前端自动添加的。没有它们,您将收到400-500范围的响应。
  • Referer——上下文头信息,由用户操作生成。许多端点检查请求是否“来自自己的页面”。
  • Authorization: Bearer <JWT>——短期令牌,通常有效期为15-60分钟。硬编码它是没有意义的:需要能够获取新的。
  • 会话cookie——将它们保存在会话对象中,而不是手动复制。
  • 正确的Content-Type用于POST:application/json和application/x-www-form-urlencoded以不同方式编码主体,声明的类型不匹配会默默破坏请求。

如果令牌不在cookie中,可以在哪里寻找它们:在HTML源代码中的<script>内(通过已知值搜索Ctrl+F),在JavaScript捆绑包中,在localStorage或IndexedDB中——在开发者工具的应用程序选项卡中。

潜在的陷阱,往往在后期才会发现

私有API会在没有警告的情况下更改。它没有版本控制、兼容性承诺和支持:前端团队在周四晚上重命名字段,您的解析器就会收集空值。保护措施不是“可靠的选择器”,而是结构控制:检查必填字段是否到位且类型正确;监控空值的比例和记录的数量;跳过损坏的记录,但如果缺陷超过10%,则发出警报;保存原始响应,以便以后进行比较。

API有时比页面的保护更严格。这种情况经常发生:HTML可以平静地返回,而在/api/上则有反机器人机制,它检查TLS指纹和头信息组合。这样,流量节省就会变成失败请求比例的增加,收益被吞噬。

签名请求。如果参数中有sign、hash或_s,前端会在JavaScript中计算签名。重现它是一个单独的项目,通常保持在HTML中更便宜。

频率限制。私有端点并不适合流量:保持每秒1-2个请求,为连接和读取设置单独的超时(例如5秒和30秒),仅在遇到瞬态错误时重试——429、500、502、503、504——而不触碰401和404。必须使用指数延迟和抖动,否则所有工作线程会同时进入第二轮。更多细节请参见代理的超时和重试逻辑。

法律框架。公开的非身份验证端点是一种情况,而登录账户则是根本不同的情况:注册意味着接受用户协议。个人数据受GDPR保护,无论它们获取的难易程度如何。事实——价格、特征、可用性——不受版权保护,与文本和图像不同。

何时保留HTML

隐藏的API并不总是有利可图。如果:

  • 网站是服务器端的,根本没有内部API;
  • 端点需要签名或令牌轮换——维护它的成本高于页面;
  • API的保护比公共页面更严厉;
  • 需要的是前端从多个来源收集的最终结果;
  • 您管理着数十个网站:统一的HTML管道比拥有各自特性的私有API动物园更易于扩展。

在API解析中选择什么类型的代理

转向JSON会改变计算,因为瓶颈发生了变化:流量变少,而对IP质量和会话稳定性的要求增加。

  • 没有身份验证且没有反机器人机制的开放端点。在这里,数据中心代理就足够了:数据量小,不需要为居民代理付费。
  • 有反机器人机制或与会话绑定的端点。需要带有粘性会话的居民代理:令牌、cookie和IP必须在整个链条中保持一致,否则服务器将在第二个请求时重置会话。与此同时,账单仍然会保持在合理范围内——在JSON模式下,千兆字节的消耗速度很慢。
  • 来自移动应用的数据。如果网页版本被关闭,而应用程序提供相同的信息更简单,则通过流量拦截查找端点——这是一个单独的过程,在关于通过mitmproxy查找移动应用隐藏API的文章中进行了详细讨论。

简而言之

在开发者工具中花二十分钟通常可以替代与无头浏览器斗争的数天:Fetch/XHR过滤器、按可见值搜索、复制为cURL——您就拥有了一个有效的请求。接下来解决细节:转移所有头信息,解析分页方案,设置响应验证,并冷静评估端点是否比页面更受保护。在私有API有效的地方,它同时减少了流量和请求数量——也就是说,立即降低了代理成本和被封禁的可能性。