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/markdownapplication/json 时返回机器格式;
  • 路径后缀:请求 /page.md 时返回 Markdown 原文(如 llms.txt 生态常用的约定)。

Nginx 示例

对 AI 爬虫 UA 重写到 .md 版本(需后端能产出 Markdown):

nginx.conf(片段)
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:

middleware.ts(示意)
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-geoNext.js 中间件,按 Accept 头 / .md 后缀 / UA 返回 Markdown 并生成 llms.txt

纯静态站怎么办

本站是纯静态站,未做服务端协商;取而代之的是:① 正文语义化、无 JS 依赖,AI 直接读 HTML 也能抽取;② 提供 llms.txtsitemap.xml 作为机器导航;③ 若上线到支持边缘函数的平台,可加一层按 UA 返回 Markdown 的中间件。对多数内容站,先把「HTML 本身干净可读」做扎实,收益已足够。

注意

  • 不要对 AI 返回与 humans 版本不一致的事实——口径统一,避免被判定为欺骗性内容;
  • Markdown 版本应保留来源链接与数据,否则失去可核验性;
  • 内容协商是「加分项」,llms.txt / robots / Schema 才是地基,先做地基。