挑战
垂直 AI 初创公司在第二个月左右都会遇到同样的壁垒。他们发布了支持 copilot、法律研究助手或合规机器人。最初的演示赢得了客户。然后数据开始老化,回答开始偏离现实。
我们看到团队将 AI 端构建得很完善,却把数据端作为后话。提取流水线只是运行在某人笔记本电脑上的一个 Python 脚本。它抓取 200 个来源 URL 一次,将干净的 Markdown 存入向量库,然后大家就开始庆祝。六周后,一半的回答引用了已删除的页面、废弃的 API 或三月份发布、五月份再次发布的产品功能。
修复方法听起来很简单: 每周重抓取每个来源。但现实更为严峻。到 2026 年,约 60% 的知名网站会屏蔽 AI 爬虫 (高于 2023 年底的 23%),而且这些保护措施不再是简单的 User-Agent 检查。它们会检查会话行为、request 节奏和握手级别的信号。一月份还能正常工作的简单脚本在三月份就会悄无声息地返回空页面。
更糟糕的是,一些网站现在会提供 tarpit 内容 (读起来像真实文章的马尔可夫生成的乱码),直到它污染了你的嵌入。因此你的工程师每周要花一半的时间来修补抓取工具,而不是发布产品。检索质量下降,客户注意到这一点,你聘请来构建 AI 的团队变成了一家抓取工具维护店。
方法
重抓取问题分解为每个 request 上必须发生的三个具体决策:
- 是否渲染? 大多数文档门户提供干净的 HTML。越来越多的网站 (任何基于 Next.js 构建的、任何客户端渲染的内容) 需要完整的浏览器渲染才能返回有用的内容。
- 哪个 proxy? 住宅、数据中心、移动、地理绑定、特定 ISP。正确的选择因目标而异。
- 它真的起作用了吗? 带有空 body 或 CAPTCHA HTML 页面的 200,是一个成功的 HTTP request,但却是一个失败的抓取。
像 FourA 这样的平台将这些中的每一项视为头等大事来处理。
对于渲染决策,针对廉价、快速的情况调用 Single,对于重度 JS 的目标调用 Browser。调用的 body 结构相同,因此你的提取代码仅针对每个源标志进行一次分支,而不是包含一百个针对特定站点的怪异处理逻辑。
对于 proxy 选择,Proxy Finder 作为每个 Single、Browser 和 Auto 调用的一部分运行。平台为每个 request 选择一个有效的出口,并在 response 中返回其不透明的 id (在 Single/Browser 的 r.proxy 顶层,或在 Auto 上的 r.session.proxy),当你需要坚持使用同一出口时,可以在后续调用中重用该 id。你的爬虫不需要拥有自己的 proxy 排名算法。(我们在 为何 Proxy 池大小在 2026 年不再重要 中写过关于为何池大小不再是区分因素的内容。)
对于“它真的起作用了吗”这个问题,每个 request 都会支持一个 validate 块。你可以声明怎样算是成功: 可接受的状态码、必需的 header 值、必须出现或不能出现的 body 字符串。FourA 会返回七种结果之一,并且只有 success 才会计费。未能通过内容规则的 200 会被标记为 application_fail,并且永远不会进入你的数据集。
以下是对需要 JS 渲染的文档门户进行重抓取调用的样子。我们让 Auto 编排,它挑选正确的产品 (Single、Proxy 或 Browser),处理机器人防御机制,并返回会话三元组,以便下一次重抓取可以继续使用同一个出口:
import requests
r = requests.post(
"https://api.foura.ai/api/auto",
headers={"Authorization": "Bearer pk_live_..."},
json={
"url": "https://docs.example.com/changelog",
"validate": {
"status": {"accept": [200]},
"data": {"accept": ["<article"], "fail": ["captcha", "Just a moment"]},
},
},
).json()
# r["data"] or r["body"] — rendered content (Auto runs the right sub-product per host;
# Single populates "data", Browser populates "body")
# r["session"] — { "proxy": "<base36 id>", "cookies": [...], "userAgent": "..." }
# On the next recrawl, pass r["session"]["proxy"] back as `ignoreProxies: [<id>]` to avoid
# the same exit, or via /api/single with `proxy: <id>` to stick to it.
如果目标抛出了 Cloudflare 插页,validate.data.fail 规则会捕获它。针对你的用量记录的结果是 application_fail。你不需要为此付费,并且你的提取代码知道该重试使用其他的 proxy,而不是将“请稍候...”页面输入到嵌入中。
对于更广泛的语料库,你可以在现有的作业队列中包装相同的模式。我们交流过的团队每晚都会与之前的抓取进行对比,仅对实际更改的文档重新进行嵌入,并在几个小时的时间内刷新了包含 500 个数据源的语料库。作业队列仍然是你的。Proxy 的变动、渲染的决策、成功与否的裁决都是我们的。
成果
一旦基础设施不再是瓶颈,新鲜度循环的样子 (基于我们在垂直 AI 团队中看到的模式的说明性场景):
- 每周重抓取 500 个源 URL,而不是启动时的一次性 200 个 URL
- 在抓取工具上的工程时间: 每周不到 2 小时,从 1-2 天减少
- 检索过时窗口: 5-7 天,而不是无限期
- 向量库中的垃圾率接近于零,因为 Cloudflare 插页和 tarpit 页面在到达你的嵌入模型之前会在
validate层被拒绝 - 每个数据源的成本可预测,因为失败的抓取不会出现在账单中
重点并不是这些有多神奇。重点是它们很无聊。而无聊正是生产 AI 所需要的。(有关托管 LLM 提取何时不再划算的更多信息,请参见 托管 LLM 提取何时不再划算。)
关键要点
大多数构建垂直 AI 的团队认为护城河是 prompt、模型选择或检索算法。但并不是。护城河是新鲜度循环: 日复一日保持知识库真实性的毫不起眼的基础设施。
到 2026 年,在垂直 AI 领域获胜的团队不会是拥有最聪明 prompts 的团队。而是那些其用户从未察觉到数据是否为最新的团队,因为数据永远是最新的。