尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

为什么你的llms.txt没有爬虫访问?部署与日志排查指南

为什么你的llms.txt没有爬虫访问?部署与日志排查指南 看到 Nobody Fetched My Llms.txt 这个标题我第一反应很直接作者把 llms.txt 文件放到了网站根目录满心期待 GPTBot、ClaudeBot 这些大模型爬虫来抓取结果翻遍服务器日志除了自己手动 curl 测试的那一次一个相关请求都没有。这个现象并不是个例。llms.txt 是近两年网站管理领域经常被讨论的一份文件作用是在 robots.txt、sitemap.xml 之外给大型语言模型提供一个更友好的内容入口清单。它可以让 LLM 爬虫更快理解站点结构、筛选有效链接、减少无效抓取。但它不是收录加速器也不是搜索引擎提交工具。这篇文章会从标准规范、创建方式、服务器配置、验证方法、日志排查几个层面展开重点回答一个核心问题为什么你写了 llms.txt却一直没有大模型爬虫来访问以及怎么判断问题出在哪里。1. 核心能力速览能力项说明项目/标准类型Web 文件规范类似 robots.txt 和 sitemap.xml 的补充提出背景由 Fast.ai 创始人 Jeremy Howard 等人提出目的是给 LLM 爬虫提供站点内容的 Markdown 索引文件位置网站根目录例如https://example.com/llms.txt文件格式纯文本使用 Markdown 语法组织标题、摘要和链接读取方GPTBot、ClaudeBot、Google-Extended、PerplexityBot、CCBot 等 LLM 爬虫以及使用相关工具的人工访问主要作用让大模型爬虫快速识别网站重点页面降低抓取成本提高内容被理解的概率需要安装的组件无只需要一个能放静态文件的 Web 服务器支持的平台任意 Web 服务器Nginx、Apache、Caddy、IIS、对象存储静态站点等资源占用极小一个文本文件通常几十 KB 以内是否需要 API不需要文件本身通过 HTTP GET 获取是否支持批量任务文件内容是静态文本批量生成和批量校验可以由脚本完成适合场景技术博客、文档站、资料库、导航页、个人站点llms.txt 的价值不在于“被某个搜索引擎收录”而在于当 LLM 爬虫已经到达你的站点之后它能用最少的请求拿到最有价值的页面清单。你可以把 llms.txt 理解成一份给大模型看的“待办事项表”先看标题再看摘要然后挑链接去抓取。相比让爬虫自己漫无目的地遍历整站llms.txt 能显著降低站点被“翻箱倒柜”的概率。不过要注意llms.txt 不会主动吸引爬虫。如果一个爬虫根本不知道你的域名它不会因为根目录存在一个 llms.txt 就自动出现。这也是“Nobody Fetched My Llms.txt”这句话最核心的矛盾点文件本身没有问题但很多站长把它当成了引流的工具而实际它的定位是“让已经来的爬虫少走弯路”。2. 适用场景与使用边界llms.txt 适合以下类型的站点技术博客、开源项目文档、在线教程、API 文档、知识库、个人导航页。这类站点的共同特点是内容以文本为主页面之间有清晰的层级关系而且站点维护者希望内容被 AI 工具引用。对于这类站点一份干净的 llms.txt 能明显提升爬虫抓取的有效性。不适合放 llms.txt 的场景也有不少。比如需要登录才能访问的私有系统、内部知识库、动态内容占比极高的应用后端、包含大量付费墙内容的媒体站。这类站点即使放了 llms.txt爬虫拿到的也只是入口 URL实际内容仍然无法访问反而可能暴露不该暴露的路径。这里有一个容易被忽略的边界llms.txt 中的每个链接都应该是公开、可访问、不需要登录就能抓取的页面。只要有一个链接指向受限内容爬虫就会得到一次 403 或 302影响整份文件的信任度。从合规角度看需要明确一点llms.txt 不等于“放弃版权”。它描述的是“我允许哪些公开页面作为入口”但并不改变内容本身的版权归属。如果站点内容包含他人的图片、文字、代码或涉及肖像、声音、个人信息写入 llms.txt 前必须先确认授权。更稳妥的做法是只列自己原创的公开页面不要放带隐私信息的 URL不要在摘要里出现用户 ID、订单号、邮箱等敏感字段。另外一个常见误区是“放了 llms.txt 就代表允许所有 AI 抓取”。这种理解并不准确。LLM 爬虫是否抓取你的站点还要看 robots.txt 是否允许对应 User-Agent以及爬虫自身是否遵循 llms.txt 规范。你可以在 robots.txt 中限制某个爬虫的抓取范围同时仍然提供 llms.txt 给其他合规爬虫阅读。3. 环境准备与前置条件llms.txt 对硬件和软件的要求几乎可以忽略但部署前需要确认几个前置条件。首先是域名和服务器。llms.txt 必须放在站点根目录也就是访问https://你的域名/llms.txt能直接打开文件。这意味着你需要一个已经解析到 Web 服务器的域名并且服务器上跑着 Nginx、Apache、Caddy 或等价物。纯前端托管平台也适用例如 GitHub Pages、Cloudflare Pages、对象存储静态网站只要根目录可以自定义文件。其次是 HTTP 访问通畅。用浏览器直接访问https://你的域名/llms.txt应该能显示纯文本内容而不是弹出下载框也不是 404。如果当前站点本身需要登录才能访问那 llms.txt 也会被登录拦截等于白写。第三是 robots.txt 的配合。检查站点根目录下的 robots.txt确认没有对常见的 LLM 爬虫设置全局Disallow: /。如果 robots.txt 禁止了所有爬虫很多 LLM 爬虫根本不会去读 llms.txt因为它第一步就被拦住了。下面是一个可参考的基础配置User-agent: * Allow: / User-agent: GPTBot Allow: / User-agent: ClaudeBot Allow: /这里不展开所有爬虫的 User-Agent只说明一个原则llms.txt 要生效前提是对应爬虫被 robots.txt 允许。常规搜索引擎的抓取配置也应该同时保留。第四是工具准备。验证 llms.txt 并不需要重型环境只需要命令行 curl、Python 3、以及一个能查看 Web 服务器访问日志的终端权限。如果你使用 Windows 服务器也可以用 PowerShell 的Invoke-WebRequest做同样的访问测试。最后是文件编码。llms.txt 应该使用 UTF-8 编码保存避免出现中文乱码。绝大多数 Web 服务器默认对.txt文件返回text/plain; charsetutf-8但如果服务器没有显式配置 charset部分爬虫可能会用默认编码解析导致中文标题乱码。这个问题在 Nginx 和对象存储静态站点上比较常见。4. 创建 llms.txt 与服务器配置先看一个最小可用的 llms.txt 示例。按 llmstxt.org 的规范文件结构大致是# Example.com 文档索引 Example.com 是一个关于 Python 开发、Linux 运维和 AI 工具的中文技术站点。 ## 常用页面 [首页](https://example.com/): 站点首页包含最新文章和更新说明 [Python 入门教程](https://example.com/python-basics): 面向初学者的 Python 教程 [Linux 运维手册](https://example.com/linux-ops): 常用运维命令与排查清单 [AI 工具实测](https://example.com/ai-tools): 本地部署工具的安装与测试流程 ## 其他资源 [sitemap.xml](https://example.com/sitemap.xml): 完整 URL 列表第一行是 H1 标题前缀是摘要块后面用 H2 分组每个链接使用 Markdown 语法链接后面用冒号加描述。规范本身并不复杂核心是让文件保持简短、结构清晰。如果你只是把全站所有 URL 倒进 llms.txt文件体积会变大爬虫反而不知道该抓哪里。写完文件后上传到 Web 服务器根目录。接下来建议显式配置 Content-Type防止某些服务器把.txt文件识别成application/octet-stream导致浏览器和爬虫把它当成下载文件。Nginx 可以这样配置location /llms.txt { default_type text/plain; charset utf-8; add_header Cache-Control public, max-age3600; }如果使用 Apache可以在根目录的.htaccess或虚拟主机配置里加一行Files llms.txt ForceType text/plain /Files对象存储静态站点通常可以在控制台上设置文件 Content-Type上传时手动指定为text/plain; charsetutf-8即可。robots.txt 也需要检查。虽然 llms.txt 是一个独立文件但很多 LLM 爬虫在抓取前会先读取 robots.txt。如果你的 robots.txt 对某个爬虫写了Disallow: /它就不会继续访问 llms.txt。下面是允许常见 LLM 爬虫抓取根目录的参考配置User-agent: GPTBot Allow: / User-agent: ClaudeBot Allow: / User-agent: Google-Extended Allow: /这里需要特别说明Google-Extended是 Google 用于控制 AI 训练抓取的 User-Agent它和普通 Googlebot 抓取搜索索引的逻辑不一样。是否允许它取决于你是否希望自己的内容被用于训练 Gemini 等模型。如果你不希望内容被用于训练可以只允许普通搜索爬虫不开放Google-Extended。这是内容授权问题不是技术问题需要自己权衡。5. 功能测试与效果验证部署完成后先做最基本的可达性测试。打开终端执行curl -I https://example.com/llms.txt如果返回200 OK并且Content-Type是text/plain; charsetutf-8说明文件已经能正常访问。再用下面的命令看文件前几行curl -s https://example.com/llms.txt | head -n 20# Example.com 文档索引 Example.com 是一个关于 Python 开发、Linux 运维和 AI 工具的中文技术站点。 ## 常用页面 [首页](https://example.com/): 站点首页包含最新文章和更新说明 [Python 入门教程](https://example.com/python-basics): 面向初学者的 Python 教程到这一步已经确认了“你的网站能提供 llms.txt”。接下来要验证文件内容是否可以被程序化解析。下面是一个 Python 检查脚本它会读取 llms.txt提取标题、摘要和所有链接并检查每个链接的 HTTP 状态import re import requests from urllib.parse import urljoin BASE_URL https://example.com LLMS_URL BASE_URL /llms.txt session requests.Session() def check_llms_txt(): resp session.get(LLMS_URL, timeout15) resp.raise_for_status() text resp.text lines text.strip().splitlines() current_section for line in lines: line line.strip() if not line: continue if line.startswith(# ): print(站点标题:, line[2:].strip()) elif line.startswith( ): print(站点摘要:, line[2:].strip()) elif line.startswith(## ): current_section line[3:].strip() print(分区:, current_section) elif re.match(r^\[.\]\(.\), line): title, url _parse_link(line) print(f链接: {title} - {url}) _check_link(url) def _parse_link(line): title_end line.index(]) url_start line.index(]() 2 url_end line.index(), url_start) title line[1:title_end] url line[url_start:url_end] return title, urljoin(BASE_URL, url) def _check_link(url): try: r requests.head(url, timeout10, allow_redirectsTrue) status r.status_code except requests.RequestException: status ERR print(f 状态码: {status}) if __name__ __main__: check_llms_txt()这个脚本不依赖额外框架只用了requests。如果你的服务器没有安装可以用pip install requests补上。脚本输出会列出每条链接的状态码凡是出现 404、403、ERR 的都需要回到站点上处理。链接有效性直接决定 llms.txt 被爬虫信任的程度这一项值得多花时间检查。接下来是本文最核心的验证确认到底有没有 LLM 爬虫来抓取过你的站点。方法很简单查看 Web 服务器的访问日志。Nginx 日志默认位置通常是/var/log/nginx/access.logApache 是/var/log/apache2/access.log。用 grep 过滤常见 LLM 爬虫 User-Agentgrep -iE GPTBot|ClaudeBot|PerplexityBot|Google-Extended|CCBot|OAI-SearchBot /var/log/nginx/access.log | tail -n 50如果没有任何输出说明日志里没有出现过这些爬虫的请求。但先不要急着下结论还要确认日志格式是否记录了 User-Agent。部分 Nginx 配置的 access_log 默认格式不包含 UA 字段这种情况下即使爬虫来过你也查不到。更保险的做法是先手动构造一个带 GPTBot User-Agent 的请求然后去日志里搜索用已知流量验证日志链路的完整性curl -A GPTBot/1.0 -s -o /dev/null https://example.com/llms.txt sleep 1 grep GPTBot /var/log/nginx/access.log | tail -n 5如果这条手动请求能在日志里出现说明日志记录完整之前的空结果才是真实数据如果手动请求也搜不到就要先修日志配置否则之后所有监控都是盲人摸象。6. 接口 API 与批量任务llms.txt 本身是静态文件不是接口服务但很多站点会面对一个实际问题页面数量很多靠手工维护 llms.txt 不现实。这时候可以写一个批量生成脚本从 sitemap.xml 读取 URL 列表自动生成 Markdown 格式的 llms.txt。下面是一个通用思路的 Python 示例实际使用时需要按自己的站点结构替换逻辑from urllib.request import urlopen import re SITEMAP_URL https://example.com/sitemap.xml OUTPUT_FILE llms.txt def fetch_sitemap(url): with urlopen(url, timeout15) as resp: return resp.read().decode(utf-8) def extract_urls(xml_text): return re.findall(rloc(.*?)/loc, xml_text) def url_to_title(url): path url.rstrip(/).split(/)[-1] title path.replace(-, ).replace(_, ).title() return title or 首页 def build_llms_txt(base_url, raw_urls): lines [# Example.com 文档索引, ] lines.append( 本站点公开文档与教程列表。) lines.append() lines.append(## 内容页面) lines.append() for url in raw_urls: title url_to_title(url) lines.append(f[{title}]({url}): 关于{title}的完整内容。) return \n.join(lines) if __name__ __main__: sitemap_xml fetch_sitemap(SITEMAP_URL) urls extract_urls(sitemap_xml) content build_llms_txt(SITEMAP_URL, urls) with open(OUTPUT_FILE, w, encodingutf-8) as f: f.write(content) print(f已生成 {len(urls)} 条链接输出到 {OUTPUT_FILE})这个脚本的核心问题是从 URL 里推断出的标题不一定准确描述文本也是通用的需要人工检查。更好的做法是让站点后台在发布文章时同步输出 llms.txt或者用模板渲染时直接把页面标题和摘要写进去。生成后的批量校验也可以自动化。下面这个脚本遍历 llms.txt 中所有链接使用并发请求检查状态码并把异常结果输出到文件import re import requests from concurrent.futures import ThreadPoolExecutor LLMS_TXT llms.txt OUTPUT broken.txt def parse_links(text): pattern re.compile(r\[.*?\]\((.*?)\)) return pattern.findall(text) def check_url(url): try: response requests.head(url, timeout10, allow_redirectsTrue) return url, response.status_code except Exception as e: return url, ERR with open(LLMS_TXT, r, encodingutf-8) as f: text f.read() links parse_links(text) with ThreadPoolExecutor(max_workers8) as executor: results list(executor.map(check_url, links)) with open(OUTPUT, w, encodingutf-8) as f: for url, status in results: if status ! 200: f.write(f{status} {url}\n) print(f检查 {len(links)} 条链接异常信息写入 {OUTPUT})批量任务的思路不复杂核心是不要让 llms.txt 停留在“手工写一次就丢下”的状态。站点结构变化时llms.txt 会慢慢失真最终爬虫读到的链接大量失效反而降低站点质量。7. 资源占用与性能观察llms.txt 本身几乎不占用资源一个文件通常只有几 KB 到几十 KB访问频率也远低于普通页面。真正需要观察的不是这个文件而是 LLM 爬虫对整个站点的抓取行为。当爬虫读取 llms.txt 后它可能短时间内对清单里的多个 URL 发起并发请求这种请求风暴才是站长应该关注的。最直接的观察方式是分析访问日志。下面的命令可以统计 llms.txt 每天被请求的次数以及请求来源 IPgrep llms.txt /var/log/nginx/access.log | awk {print $1} | sort | uniq -c | sort -rn输出结果里第一列是请求次数第二列是客户端 IP。看到陌生 IP 段持续请求 llms.txt是正常现象说明某种爬虫已经发现了文件。如果只看到你自己的 IP说明还没有外部爬虫来过。可以用类似方法统计所有请求的 User-Agent 分布awk {for (i1; iNF; i) if ($i ~ /^\(GPTBot|ClaudeBot|PerplexityBot)/) print $i} /var/log/nginx/access.log | sort | uniq -c | sort -rn性能上建议给 llms.txt 设置短缓存时间。因为我们可能随时调整文件如果缓存时间过长爬虫会一直拿着旧版本文件。通常设置max-age3600足够。想要彻底避免缓存问题可以完全不加 Cache-Control 头但那样会增加少量请求负担。对于个人站点来说1 小时缓存是折中方案。分辨率、步数、批量大小这些 AI 生成任务里的性能指标在 llms.txt 场景里没有对应概念。这里要换成另一个维度文件体积和链接数量。如果 llms.txt 超过 100 KB或者包含数百条链接建议压缩到只剩下核心页面把长尾内容留给 sitemap.xml。LLM 爬虫处理超长清单的耐心有限文件越短每条链接被重视的概率越高。8. 常见问题与排查方法问题现象可能原因排查方式解决方案访问 /llms.txt 返回 404文件没有上传到根目录或文件名大小写不对检查服务器目录和文件列表把文件放到docroot根目录保持小写文件名浏览器访问变成下载文件服务器的 MIME 类型识别错误查看响应头中的 Content-Type强制设置为text/plain; charsetutf-8文件内容中文乱码文件不是 UTF-8 编码或响应头缺少 charset用编辑器另存为 UTF-8 无 BOM在服务器配置中显式设置 charsetrobots.txt 允许了所有爬虫但 llms.txt 仍没被访问站点整体发现性不足爬虫根本没进入站点检查日志中是否有普通搜索引擎爬虫先提升站点收录再观察 llms.txt 请求爬虫请求了首页但没有请求 llms.txt爬虫不兼容 llms.txt 规范或 robots 规则限制查看爬虫日志和 UA 对应的 robots 规则确认 robots.txt 中对应 UA 没有被 Disallowllms.txt 中部分链接返回 404页面被删除或 URL 结构变化运行链接批量校验脚本更新 llms.txt 中的链接或添加跳转规则检查日志时搜不到 GPTBot 等 User-Agentaccess_log 格式不包含 UA 字段手动带 UA 请求后再次搜索修改 Nginx log_format增加$http_user_agent文件能访问但内容被爬虫忽略链接格式不规范或描述信息太少按 llmstxt.org 语法重新整理每个链接只保留一条简短描述避免无效重复这里重点解释一下“爬虫请求了首页但没有请求 llms.txt”的情况。很多 LLM 爬虫在首次进入未知站点时会先抓 robots.txt 和首页然后根据页面内容决定要不要继续。llms.txt 规范还在推广阶段并不是所有爬虫都会无条件尝试读取。如果你的站点首页内容质量足够爬虫可能走常规 HTML 抓取路线不依赖 llms.txt。这并不意味着文件白写只是爬虫策略不同。另一个容易被忽略的问题是多域名。如果你在example.com放了 llms.txt但用户实际访问的是www.example.com爬虫看到的根目录可能是www.example.com/llms.txt。如果没有做 301 跳转或者两边内容不一致爬虫就会拿到不同的结果。最稳妥的做法是让主域名和 www 域名统一跳转到同一个地址然后在该地址的根目录放置 llms.txt。如果日志检测结果显示“完全没有 LLM 爬虫来过”先不要怀疑 llms.txt 内容大概率是站点本身的发现性问题。建议先看普通搜索引擎爬虫是否访问过你比如 Googlebot、Bingbot、Baiduspider。如果这些常规爬虫也不来说明站点还没有被收录或者 robots.txt 设置太严格。llms.txt 只能解决“爬虫来了之后往哪走”的问题不能解决“爬虫怎么知道你”的问题。9. 最佳实践与使用建议第一llms.txt 要短。只保留建站以来最有价值的几十个页面正文、教程、工具页优先标签页、搜索页、分页器一律不要放。爬虫抓取列表不是索引采集它需要的是高质量入口不是全站 URL 备份。第二文件要和站点实际结构保持同步。每发布一篇新文章就把对应链接加入 llms.txt每删除一篇旧页面就从文件里移除对应条目。如果嫌人工维护麻烦就用后台上搭建自动生成流程但生成后仍然需要一套定期校验脚本确保没有 404。第三别让 llms.txt 代替 sitemap.xml。sitemap.xml 是给搜索引擎爬虫用的完整 URL 清单llms.txt 是给 LLM 用的精选入口清单两者是互补关系。建议在 llms.txt 末尾保留一条指向 sitemap.xml 的链接让爬虫需要更多内容时继续读取完整清单。第四保持文件名严格为llms.txt不要改成llm.txt、llms.txt.txt或LLMS.TXT这类变体。大多数爬虫和工具会按照固定路径访问根目录的llms.txt文件名不对等于文件不存在。第五定期检查 robots.txt。很多站点升级安全策略时会顺手把某些爬虫封掉导致之前正常的 llms.txt 访问突然停止。建议每次修改 robots.txt 后都用第 5 节的命令重新验证一次日志。第六新增内容时优先保证 HTTP 状态码正常。llms.txt 的价值建立在链接有效的基础上。一次站点改版导致大量 URL 变更会让整个文件瞬间失去意义。如果确实需要改 URL尽量给旧地址加 301 跳转让 llms.txt 里的旧链接也能间接有效。第七对外宣传时不要过度承诺。llms.txt 不会保证你的内容被 ChatGPT 引用也不会保证出现在 Perplexity 的答案里。它只是降低了爬虫理解站点的成本。如果你在社区里推广站点合理的说法是“本站点支持 llms.txt”而不是“本站已被 AI 收录”。第八内容合规要落实。不要在 llms.txt 里放任何需要权限才能访问的资源不要放第三方版权内容不要放用户隐私数据。即便某个爬虫没有按 robots.txt 执行它抓取到的公开入口也不应该暴露出敏感信息。所有 URL 在写入前都应人工确认对应页面本身可以公开访问。10. 总结与下一步llms.txt 是一个值得部署的小标准但部署只是第一步。先用半小时写好文件上传到网站根目录用 curl 验证 Content-Type再用 Python 脚本检查链接有效性。之后把日志监控挂起来定期 grep GPTBot、ClaudeBot、PerplexityBot 这些 User-Agent观察是否有外部爬虫访问过文件。如果两周后日志里仍然只有你自己不用反复修改 llms.txt 格式问题大概率出在站点本身的可发现性上。先检查 robots.txt 是否挡路再用 Search Console 或 Bing Webmaster Tools 查看常规搜索引擎的抓取记录最后评估站点的外链和内容更新频率。llms.txt 的存在是为了让已经到达的爬虫更高效地工作而让爬虫到达站点这件事还需要更完整的站外运营体系来支撑。把 llms.txt 当作一个运维习惯去维护而不是当作一个快速见效的 SEO 插件。它不会立刻带来流量但会在内容质量和抓取效率上提供长期回报。
返回列表