Dev.to AI 🤖 Ai 👁 0

文档站怎么让 AI 读懂:llms.txt、Markdown 副本与三个踩过的坑

去年开始有个变化:我们的文档站,来自 ChatGPT、Perplexity 的引荐流量超过了来自 Google 搜索的。 但有个前提 —— 我们花了大半年把文档站改造成机器可读的。改之前,那些 AI 爬虫来抓的时候,看到的是一片空白。 这篇文章讲具体做了什么,以及踩过的坑。所有东西都是公开可查的,你可以直接对着自己的站验证。 先搞清楚 AI 爬虫看到的是什么 多数 AI 爬虫(GPTBot、ClaudeBot

去年开始有个变化:我们的文档站,来自 ChatGPT、Perplexity 的引荐流量超过了来自 Google 搜索的。

但有个前提 —— 我们花了大半年把文档站改造成机器可读的。改之前,那些 AI 爬虫来抓的时候,看到的是一片空白。

这篇文章讲具体做了什么,以及踩过的坑。所有东西都是公开可查的,你可以直接对着自己的站验证。

先搞清楚 AI 爬虫看到的是什么

多数 AI 爬虫(GPTBot、ClaudeBot、CCBot、PerplexityBot)不执行 JavaScript。

所以对一个用 Next.js / Vue / React 做的站点,它们拿到的是初始 HTML。如果你的正文靠客户端渲染,它们看到的就只有一个 <div id="root">。

判断方法很简单,比任何工具都快:

curl -sS https://你的域名/某一篇文档 | grep -c "正文里的某个词"

返回 0,说明正文没在初始 HTML 里,AI 爬虫也看不到。

第一步:llms.txt

这是目前事实上的行业约定(不是正式标准,但被广泛采用),放在站点根目录,是一个给大模型看的导航文件。

结构大概是:

# 站点名

> 一句话说明这个站是什么

## 文档
- [快速开始](https://example.com/quickstart): 三步接入
- [API 参考](https://example.com/api): 完整接口说明

## Optional
- [定价](https://example.com/pricing)

关键是每条都带一句描述。纯链接列表对 LLM 没什么用,因为它不知道点进去会看到什么。

如果你有多个语言版本,给每个语言各一份(/en/llms.txt、/ja/llms.txt)。注意:没有翻译的页面,不要生成指向该语言的链接,否则 AI 会抓到一个语言标记错误的页面。

第二步:每篇文档的 Markdown 副本

llms.txt 解决的是「有哪些页面」,解决不了「页面内容怎么高效取走」。

解法是给每篇文档提供一个纯 Markdown 版本,路径可以是 /llms.mdx/<slug>/content.md 这种。HTML 里带上指向它的 link 标签,llms.txt 里的链接直接指向 Markdown。

更好的是做内容协商 —— 同一个 URL,根据 Accept 头返回不同格式:

curl -H "Accept: text/markdown" https://你的域名/quickstart

返回 Markdown,而不是 HTML。这样 AI 抓一个地址就能拿到干净正文,省掉解析 HTML 的开销和噪声。

这一步的收益比想象中大。HTML 里导航、页脚、样式类名占了大半体积,去掉之后 token 数可能少一半以上。

第三步:结构化数据

JSON-LD 解决的是「这段文字是什么」的问题。

文档站最值得加的几类:

  • TechArticle / Article —— 页面主体,带 datePublished / dateModified
  • BreadcrumbList —— 层级关系
  • FAQPage —— 页面上真实的问答,这个对 AI 引用帮助很大
  • SoftwareApplication —— 如果站点是产品文档
  • WebSite —— 站点本身

有个坑:FAQPage 里的内容必须真的在页面上出现。拿结构化数据标记页面上没有的内容,Google 会判定为垃圾,反而扣分。我们是从正文里解析出问答再生成 JSON-LD,不是另写一份。

第四步:sitemap 带 lastmod

sitemap 里 lastmod 的重要性在 AI 时代上升了。爬虫预算有限,它需要判断哪些页面值得重抓。

我们的做法是让每一条都带 lastmod,取自内容的 git 提交时间。663 条 URL,一条不缺。

顺便说 robots.txt。除了常规的 Allow,现在可以加 Content-Signal 之类的声明,表达「允许抓取用于搜索索引」「是否允许用于训练」的意图。这个字段各家支持程度不一,但写上没坏处。

踩过的三个坑

坑一:html lang 恒为默认语言。

这是最隐蔽的一个。我们的站是多语言的,但静态 HTML 里的 <html lang> 一律写死成 zh-CN,靠首帧前的一段内联脚本按路径改成 en 或 ja。

浏览器里看不出问题,因为脚本跑得很快。但不执行 JS 的爬虫读到的永远是 zh-CN —— 所有外语页面的语言标记都是错的。

修法有两种:构建后批量改写各语言目录下 HTML 的 lang 属性,或者给每个语种单独的 root layout。都不难,但发现它花了好几个月。

验证方法:

curl -sS https://你的域名/en/某页 | grep -o '<html[^>]*lang="[^"]*"'

坑二:外语页面被当成重复内容。

一开始我们把所有页面在所有语言下都生成了 URL,结果 /en/quickstart 和 /quickstart 内容完全一样(因为没翻译,是回退的)。

解法是区分「翻译过的」和「回退的」两种情况:回退页面仍然有 URL(访问不 404),但 canonical 指回原语言页面,hreflang 只声明真实存在的语言,并且不进 sitemap。

不这么做的话,站内会出现大量重复内容,白白稀释权重。

坑三:改完就以为 AI 会引用你。

这是认知上的坑。上面所有工作做完,只解决了一件事:让 AI 能顺利拿到你的内容。

它是否引用你,取决于另外三件事:正文能不能被整段抽取(别把关键结论埋在流程图里)、你的品牌在多个来源的表述是否一致、以及站外有没有权威提及。

第三条是决定性的,也是最难做的。文档站做得再工整,站外没人提你,AI 就是想引用也找不到依据。

一点数据

改造之后,我们观察到的是:AI 爬虫的抓取频次明显上升,某些页面在 Perplexity 的引用里开始出现。但这个过程是渐进的,不是开关式的。

如果你打算做,我的建议是先做前两步(llms.txt + Markdown 副本),投入最小,见效最快。结构化数据和 sitemap 优化是长期工程,收益更慢但更稳。

内容协商、JSON-LD 和 sitemap 的具体实现可以看我们的文档站,代码是开源的风格,机器可读部分都摆在明面上:
docs.aicentos.com/llms.txt
docs.aicentos.com/sitemap.xml

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.