手写 llms.txt 验证器:让 AI 更愿意引用你的网站(GEO)
GEO(Generative Engine Optimization,生成式引擎优化)这两年火起来,核心目标是让 ChatGPT、Perplexity 这类 AI 在回答问题时更愿意引用你的内容。其中有个越来越被认可的入口,叫 llms.txt:一个放在网站根目录、专门给大模型看的说明文件。
llms.txt 由 llmstxt.org 提出,格式是纯 Markdown。它告诉 AI:这个站是干什么的、有哪些重点文档、哪份是完整版。文件规范不难,但手写容易漏。这篇写一个验证器,按规范自动校验你的 llms.txt 写得对不对。
规范原文看这里:llmstxt.org,具体字段和示例在它页面里有详细说明。
规范要点回顾
llms.txt 的基本结构是这样:
markdown
# 站点名称
> 一句话描述这个网站是干什么的
- [产品介绍](https://example.com/products): 核心产品与参数说明
- [使用文档](https://example.com/docs): 完整使用手册
- [完整版](https://example.com/llms-full.txt): 全站内容合并版
三块内容:H1 标题、块引用描述、一组带描述的链接。可选的是用 H2 给链接分组。
工具能检查什么
llms.txt是否存在、能否访问(HTTP 200)Content-Type是否合理- 第一行是不是 H1 标题
- 有没有块引用描述
- 链接格式是否符合
- [文本](url): 描述 - 有没有建议链接
llms-full.txt - 链接可访问性抽样
依赖:requests。
完整代码
python
# -*- coding: utf-8 -*-
"""
llms.txt 验证器
用途:按 llmstxt.org 规范校验网站的 llms.txt 文件
依赖:pip install requests
"""
import re
import requests
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0 Safari/537.36"}
H1_RE = re.compile(r"^#\s+\S")
BLOCKQUOTE_RE = re.compile(r"^>\s*")
LINK_RE = re.compile(r"^-\s*\[([^\]]+)\]\(([^)\s]+)\)(?::\s*(.*))?$")
def fetch(url):
try:
resp = requests.get(url, headers=HEADERS, timeout=10)
return resp.status_code, resp.text, resp.headers.get("Content-Type", "")
except requests.RequestException as e:
return None, "", str(e)
def validate(base_url):
url = base_url.rstrip("/") + "/llms.txt"
print(f"校验目标: {url}\n" + "=" * 60)
code, text, ctype = fetch(url)
if code != 200:
print(f"[错误] llms.txt 无法访问 (HTTP {code})")
return
print(f"[信息] Content-Type: {ctype}")
if ctype and not any(k in ctype for k in ("text/plain", "text/markdown", "octet-stream")):
print(f" [警告] Content-Type 建议为 text/plain,当前是 {ctype}")
lines = text.splitlines()
errors, warnings, links = [], [], []
# 1. H1 标题
if not lines or not H1_RE.match(lines[0].strip()):
errors.append("第一行必须是 H1 标题(# 站点名)")
else:
print(f"[通过] 标题: {lines[0].strip()}")
# 2. 块引用描述
if not any(BLOCKQUOTE_RE.match(l.strip()) for l in lines):
warnings.append("缺少块引用(> 描述),建议加一句站点介绍")
# 3. 链接解析
for i, line in enumerate(lines, 1):
m = LINK_RE.match(line.strip())
if m:
links.append((m.group(1), m.group(2), (m.group(3) or "").strip(), i))
if not links:
errors.append("没有任何链接,llms.txt 至少要有一个文档链接")
# 4. llms-full.txt
if not any("llms-full.txt" in u for _, u, _, _ in links):
warnings.append("建议链接到 llms-full.txt(完整版)")
print(f"\n共 {len(links)} 个链接:")
for text, u, desc, ln in links:
tip = "" if desc else "(建议补一句描述)"
print(f" 第{ln}行: [{text}]({u}) {tip}")
# 5. 可访问性抽样(最多10个)
print("\n[检查] 链接可访问性抽样:")
for text, u, desc, ln in links[:10]:
c, _, _ = fetch(u)
mark = "OK" if c == 200 else f"HTTP {c}"
print(f" {mark} {u}")
print("\n[错误]", len(errors))
for e in errors:
print(" -", e)
print("[警告]", len(warnings))
for w in warnings:
print(" -", w)
print("\n" + "=" * 60)
print("校验结束。规范细节见 llmstxt.org。")
if __name__ == "__main__":
validate("https://example.com")
怎么用
bash
pip install requests
把最后一行 validate(...) 里的域名换成你自己的,运行。它会在域名后自动拼上 /llms.txt。
三个写 llms.txt 时最常犯的错
第一行不是 H1。 有人第一行直接写链接或者空行,AI 读起来不知道这个文件叫什么、是哪个站。第一行必须是 # 站名。
链接没有描述。 光给一个 - [文档](https://...),AI 不知道这个链接讲什么、值不值得去读。每条链接后面加一句描述,是让 AI 愿意点进去的关键。
没给完整版。 如果你的内容比较多,把全站合并成一个 llms-full.txt,在 llms.txt 里指过去。这样 AI 一次就能拿到全量内容,不用挨个链接爬。
写在最后
llms.txt 是 GEO 里投入小、见效直接的一步,一个文件就能让 AI 更清楚你的站。代码拿去用,跑一遍就知道自己的文件合不合规。觉得有用欢迎点赞、收藏、转发,有疑问评论区留言或私信交流。