网站从多页架构重构成单页应用(SPA)后,单页应用 AI 爬虫抓取失败是最常见也最隐蔽的翻车点:页面在浏览器里显示正常,GPTBot、豆包、Kimi 这类 AI 爬虫却只拿到一个几乎空白的 HTML 空壳。正文、链接、结构化数据全由 JavaScript 在客户端二次生成,而主流 AI 爬虫不执行 JavaScript——它们看到的和用户看到的,是两个网站。
本文给出可落地的验收流程:先讲清哪些爬虫渲染、哪些不渲染,再用一套三层暴露对照法比对原始源码、渲染后 DOM 与各爬虫实际所见,接着给出链接发现与正文暴露的通过阈值、常见框架的修复对照,以及上线回归监测清单。如果你正在或即将做前端重构,建议配合从 robots.txt、WAF 到渲染与日志逐层排查的 AI 爬虫抓取诊断指南一起跑一遍。

为什么单页应用改版后 AI 爬虫抓不到正文?
根因是客户端渲染(CSR):SPA 首个请求只返回一个空的 HTML 骨架,正文要等浏览器下载并执行 JavaScript 后才注入 DOM。 用户浏览器会执行这段 JS,所以看得到;但多数 AI 爬虫拿到首个 HTML 响应就直接解析、抽取、离开,不等渲染。
结果是一种“薛定谔的正文”:在 Chrome 的 Elements 面板能看到完整文章,用“查看网页源代码”(view-source)却几乎是空的。AI 爬虫看到的是后者。 这就是改版上线后,品牌在 AI 答案里的提及和引用突然掉线的原因——内容没删,只是从爬虫视角“隐身”了。
哪些 AI 爬虫会执行 JavaScript,哪些不会?
结论先行:除 Googlebot 外,主流 AI 爬虫目前基本都不渲染 JavaScript。 据 Vercel 对其网络上 AI 爬虫抓取行为的分析,一个月内 GPTBot 抓取约 5.69 亿次、ClaudeBot 约 3.70 亿次、PerplexityBot 约 2440 万次,没有一个执行 JavaScript。它们会下载 JS 文件(GPTBot 约 11.5%、ClaudeBot 约 23.84% 的请求),但只当文本抓取,不运行。
| 爬虫 / 平台 | 归属 | 执行 JavaScript | 客户端渲染正文可见性 |
|---|---|---|---|
| GPTBot | OpenAI(训练) | 否 | 不可见 |
| OAI-SearchBot / ChatGPT-User | OpenAI(搜索/实时) | 否 | 不可见 |
| ClaudeBot | Anthropic | 否 | 不可见 |
| PerplexityBot | Perplexity | 否 | 不可见 |
| Googlebot | 是(常青版 Chromium) | 可见(渲染后) | |
| Bingbot | Microsoft | 部分渲染 | 部分可见 |
| DeepSeek / 豆包 / Kimi / 通义千问 | 各自爬虫 + 搜索后端 | 基本不执行 | 多不可见,依赖底层索引 |
有一个例外要说清:Googlebot 自 2019 年起用常青版 Chromium 渲染 JavaScript,纯 CSR 内容仍可能进入 Google 索引,进而出现在 Google AI Overviews。但这是唯一的大厂例外;Anthropic 的 web fetch 工具文档也说明,它读取的是页面返回的原始内容、不执行客户端渲染。押注“Google 看得到”,并不能让 ChatGPT、Claude、Perplexity 及国产平台看到。
国产 AI 平台(DeepSeek、豆包、Kimi、通义千问)怎么取内容?
国产平台普遍走 RAG + 联网搜索:先用爬虫或搜索后端取回原始 HTML,再喂给模型生成答案。 公开的来源结构分析显示,各平台引用来源差异很大——豆包偏抖音、今日头条、搜狐、网易、知乎;DeepSeek 近期偏淘宝、百度百科、网易;Kimi 以搜狐等为主。
这对 SPA 是双重风险:这些平台自己的抓取拿不到 CSR 正文;它们依赖的搜索索引若也没收录你的渲染内容,你就彻底出局。
客户端渲染、服务端渲染、预渲染有什么区别?
核心区别在于“正文在哪一刻、哪一层生成”:只要正文出现在服务器返回的首个 HTML 响应里,AI 爬虫就能读到;只要它依赖浏览器执行 JS 才出现,就读不到。
| 渲染方案 | 正文所在位置 | AI 爬虫可见 | 适用场景 |
|---|---|---|---|
| 客户端渲染 CSR | JS 执行后的 DOM | 否 | 后台/交互面板,不宜承载可引用内容 |
| 服务端渲染 SSR | 首个 HTML 响应内 | 是 | 需要被 AI 引用的内容型页面 |
| 静态生成 SSG / 预渲染 | 构建时生成的 HTML | 是 | 变动较少的文章、文档、落地页 |
| 动态渲染 Dynamic Rendering | 按 UA 给爬虫单独预渲染 | 是(已不推荐) | 仅作迁移过渡 |
Google Search Central 的 JavaScript SEO 基础文档已把动态渲染明确标注为“权宜之计(workaround)”,不再作为长期方案推荐,改荐 SSR、静态渲染或 hydration。新项目别再拿动态渲染当解法,直接上 SSR/SSG。 Vercel 的数据也补了一个利好:只要正文在首个 HTML 里(包括 SSR 注入的 JSON 或服务端组件输出),即便不是纯静态 HTML,AI 也能解析。
常见 SPA 框架怎么改到 AI 可见?
同一条原则落到不同框架,动作不一样:目标始终是让正文进入首个 HTML 响应。 下表按主流框架给出从“默认 CSR”到“AI 可见”的最短路径。
| 框架 | 默认渲染 | 让正文进首个 HTML 的做法 |
|---|---|---|
| React(CRA / Vite SPA) | 纯 CSR | 迁移到 Next.js(SSR/SSG)或 Remix;轻量站可用 Vike / 预渲染 |
| Vue(Vite SPA) | 纯 CSR | 迁移到 Nuxt,用 SSR 或 SSG 输出 |
| Angular | 纯 CSR | 启用 Angular SSR(原 Angular Universal)+ hydration |
| Next.js | 可 SSR | 用服务端组件 / getServerSideProps / SSG;别用 dynamic(..., { ssr: false }) 包裹正文 |
| Nuxt | 默认 SSR | 保持 ssr: true,勿设 ssr: false 退回 SPA |
| SvelteKit | 默认 SSR | 保持默认,勿对内容页全局关掉 ssr |
| Astro | 默认静态 | 默认输出静态 HTML,正文天然可见;别把正文塞进 client:only 组件 |
关键提醒:用了 SSR 框架不等于自动安全。 Next.js 里一个 ssr: false 的动态导入、Nuxt 里一处 ssr: false、或把正文塞进仅客户端组件,都会让这块内容悄悄退回 CSR。框架只是给了你 SSR 的能力,是否真的输出到首个 HTML,仍要靠下面的三层对照法验收。
抓取暴露三层对照法:原始源码 vs 渲染后 DOM vs 爬虫所见
三层暴露对照法,是把同一个 URL 的三种“可见版本”并排比对,用差异定位正文到底丢在哪一层。 这是本文的核心验收框架,任何一次改版上线都应跑一遍。
- 第一层·原始源码:
curl -sL https://你的页面取回首个 HTML,统计正文字数;或浏览器“查看网页源代码”。这就是 AI 爬虫默认拿到的内容。 - 第二层·渲染后 DOM:用无头浏览器(Playwright / Puppeteer)加载页面,读取
document.body.innerText。这是用户和 Googlebot 看到的内容。 - 第三层·爬虫所见:带爬虫 UA 请求,如
curl -A "GPTBot/1.1 (+https://openai.com/gptbot)" https://你的页面,再核对服务器日志里这些 UA 实际取到的状态码与响应体,排除被 WAF 或 robots 拦截。
判读规则:第一层与第二层的正文字数差距越大,客户端渲染泄漏越严重。 理想状态是三层内容几乎一致——原始源码里就能搜到你的关键句、标题和结构化数据。

单页应用的链接发现怎么验收?
光有正文还不够——SPA 常用 JavaScript 路由代替真实链接,AI 爬虫发现不了内页,整棵路由子树对 AI 隐身。 内容暴露和链接暴露是两件事,必须分开验收。
典型问题是把导航写成 <div onClick={() => router.push('/x')}> 而非 <a href="/x">。爬虫不执行 JS,就看不到这次跳转,也抓不到目标页。链接发现验收要点:
- 关键路由必须是真实
<a href="/path">,不能只靠onClick或按钮触发。 - 避免 hash 路由(
#/path):URL 片段不被当作独立页面。 - 无限滚动、“加载更多”之后的内容,要额外提供分页
<a href>或写进 sitemap。 - 提交 XML sitemap 列全可索引 URL,
lastmod与实际更新一致。
顺带提醒:把正文藏在登录墙、表单或点击展开之后,等于对 AI 爬虫二次隐身。 获客与可引用性之间怎么取舍,见内容放在登录墙和表单后 AI 还能不能读到。
正文与内容暴露验收清单(含通过阈值)
下面这份清单可直接作为上线门禁:每项设“通过 / 不通过”,任一不通过即阻断发布。 阈值是我们在多次 SPA 迁移诊断中沉淀的经验值,供团队对齐验收口径。
- 正文一致性:原始源码正文字数 ÷ 渲染后正文字数 ≥ 95%。
- 首屏关键信息(标题、定义、价格/参数、FAQ 答案)出现在
curl原始 HTML 中。 <title>、<h1>、meta description、JSON-LD 均在原始 HTML 内且唯一。- 关键路由 ≥ 95% 为真实
<a href>,无 hash-only 路由。 - 爬虫 UA(GPTBot / ClaudeBot / PerplexityBot / Bingbot)请求返回 200 且含正文,未被 WAF、robots 或速率限制拦截。
- XML sitemap 覆盖全部可引用页面,
lastmod准确。 - 结构化数据字段与可见正文一致,不标页面上没有的信息。
改版前后对照:一个典型 SPA 迁移的诊断样例
用三层对照法拆解一个从 Vue 客户端渲染迁到服务端渲染的内容站,能直观看到差距。 下表数值取自我们在多次 SPA 迁移诊断中反复看到的量级,供你对照自查,非单一客户实测披露。
| 指标 | 改版后(纯 CSR) | 修复(SSR)后 |
|---|---|---|
| 原始 HTML 正文字数 | ≈ 120 字(空壳) | ≈ 2,600 字 |
原始 HTML 内 <a href> 数量 |
4 | 180+ |
| GPTBot UA 取到正文 | 否 | 是 |
| 可被发现的内页路由 | 1 | 240 |
| 结构化数据出现在原始 HTML | 否 | 是 |
样例的启示很清楚:改版“看起来正常”和“AI 抓得到”是两码事。 纯 CSR 版本里,爬虫拿到的正文不足渲染后的 5%,可发现路由只剩首页一个;换 SSR 后,正文一致率和路由覆盖同时回到可用区间。决定 AI 可见度的,不是页面在浏览器里美不美,而是首个 HTML 响应里到底装了多少东西。
如果改版还要主动下线或合并部分旧页面,别直接删——先算清它们贡献了多少 AI 引用再决定跳转,参考删除或合并页面会不会丢 AI 引用。
修好之后怎么做回归监测,防止下次上线又掉?
修好只是起点:懒加载组件、A/B 实验、CDN 规则或一次前端重构,都可能在下次发布时又把正文推回客户端。 回归监测要同时盯三层信号,形成闭环。
- 上线门禁:把三层对照法写进 CI,正文一致率 < 95% 或关键路由缺失就直接 fail,不让合并。
- 日志监控:持续观察 GPTBot、ClaudeBot、Bingbot 及国产爬虫 UA 的抓取量与状态码,异常 4xx/5xx 及时告警。
- 平台侧结果监测:跟踪品牌在 DeepSeek、豆包、Kimi、通义千问的 AI 提及率、AI 搜索排名与 AI 引用来源是否随改版波动——这是最终验收,也是 MaxAEO 这类 AI 可见度监测平台的用武之地。当技术层都通过、AI 提及率却下滑,往往说明还有未覆盖的路由,或被索引延迟卡住。
把技术验收和结果监测接起来,才能把“改版掉引用”从事后救火变成上线前拦截。迁移期的完整动作清单,见网站改版怎么避免 AI 引用掉线的迁移清单。

常见问题
单页应用一定对 AI 爬虫不友好吗?
不是。问题出在客户端渲染,而不在 SPA 架构本身。用 SSR 或 SSG 把正文放进首个 HTML 响应,SPA 同样能被 AI 爬虫完整抓取。
只做了 Google 收录,为什么 ChatGPT、Kimi 还是引用不到?
因为 Googlebot 会渲染 JavaScript,而 GPTBot、ClaudeBot、PerplexityBot 等基本不渲染。Google 能看到你的 CSR 内容,不代表其他 AI 平台也能看到,两条抓取链路要分别验收。
用了 Next.js、Nuxt 这类框架就一定安全吗?
不一定。这些框架给了你 SSR 能力,但只要用 ssr: false、把正文放进仅客户端组件或 { ssr: false } 的动态导入,这块内容照样退回客户端渲染。是否真进了首个 HTML,仍要用三层对照法逐页验收。
动态渲染(给爬虫单独预渲染)现在还能用吗?
可作迁移期的过渡方案,但 Google 已将其标注为权宜之计并停止推荐,长期应迁到 SSR 或 SSG,避免维护两套渲染逻辑带来的一致性风险。
怎么快速自测正文是否暴露给了 AI 爬虫?
用 curl 取原始 HTML 统计正文字数,或在浏览器“查看网页源代码”里搜一句正文关键句。如果搜不到、字数远小于页面实际内容,就是客户端渲染泄漏。
修复后多久 AI 平台会重新收录?
取决于各平台的抓取与索引周期,通常数天到数周不等。建议持续监测 AI 提及率与引用来源,用结果确认恢复,而不是只看技术层是否通过。