TECH SPEC
内容协商:返回干净 Markdown
同一 URL,对人类返回富 HTML,对 AI 爬虫返回干净 Markdown——能显著提升可引用性。本页给实现思路与示例。
一句话
通过 HTTP 内容协商(Accept 头 / .md 后缀 / User-Agent)识别 AI 爬虫,返回无导航、无脚本的纯 Markdown 版本。
为什么做内容协商
人类页面充斥导航、广告、侧栏、脚本,这些对模型是噪声。给 AI 一份「只含正文的 Markdown」,它抽取答案的成本更低、准确率更高。研究(GEO-SFE 等)表明,纯结构/格式层面的可读性提升本身就带来可见度增益。
识别 AI 爬虫
三种常用信号,可组合:
- User-Agent:匹配
GPTBot/ClaudeBot/Bytespider等(见 robots 文档的 UA 清单); - Accept 头:包含
text/markdown或application/json时返回机器格式; - 路径后缀:请求
/page.md时返回 Markdown 原文(如 llms.txt 生态常用的约定)。
Nginx 示例
对 AI 爬虫 UA 重写到 .md 版本(需后端能产出 Markdown):
map $http_user_agent $is_ai {
default 0;
"~*(GPTBot|ClaudeBot|PerplexityBot|Bytespider|Google-Extended)" 1;
}
server {
location / {
if ($is_ai) { rewrite ^(.*)$ $1.md last; }
try_files $uri $uri/ /index.html;
}
}
Node / 框架中间件示例
在 Next.js 等框架里,用中间件按 UA / Accept 返回 Markdown:
export function middleware(req: NextRequest) {
const ua = req.headers.get("user-agent") || "";
const wantsMd = req.nextUrl.pathname.endsWith(".md")
|| (req.headers.get("accept") || "").includes("text/markdown");
if (/GPTBot|ClaudeBot|Bytespider/i.test(ua) || wantsMd) {
return NextResponse.rewrite(`/md${req.nextUrl.pathname}`);
}
return NextResponse.next();
}
现成方案
| 项目 | 做法 |
|---|---|
| dodopayments/dualmark | 基于 HTTP 内容协商的 AEO 基础设施,识别 24 个 AI bot、12 个转换器(Apache 2.0) |
| continuedev/next-geo | Next.js 中间件,按 Accept 头 / .md 后缀 / UA 返回 Markdown 并生成 llms.txt |
纯静态站怎么办
本站是纯静态站,未做服务端协商;取而代之的是:① 正文语义化、无 JS 依赖,AI 直接读 HTML 也能抽取;② 提供 llms.txt 与 sitemap.xml 作为机器导航;③ 若上线到支持边缘函数的平台,可加一层按 UA 返回 Markdown 的中间件。对多数内容站,先把「HTML 本身干净可读」做扎实,收益已足够。
注意
- 不要对 AI 返回与 humans 版本不一致的事实——口径统一,避免被判定为欺骗性内容;
- Markdown 版本应保留来源链接与数据,否则失去可核验性;
- 内容协商是「加分项」,llms.txt / robots / Schema 才是地基,先做地基。