文档站怎么让 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
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.