robots.txt 放行了整站却还是没索引:meta robots 与 noindex 误配的排查复盘

2026-09-20 01:19:16 5 次浏览
GEO网站运维NginxSEO爬虫meta robots

适用读者:负责官网、独立站运维与 SEO 的工程师;尤其是刚做完 CMS 改版、刚把 GPTBot / ClaudeBot / PerplexityBot 写进 robots.txt 白名单,却发现索引和 AI 引用一点没涨的人。

改版切流量的第 9 天,AI 搜索里能查到我们产品页的引用,从日均 40 多条掉到了 0。robots.txt 是我们自己一行行写的,GPTBot、ClaudeBot、PerplexityBot 全在 Allow 里,Google-Extended 也顺手放开了。运维老李在群里甩了一句:「放行都放行了,日志里爬虫一天来两百多次,怎么一条都不进索引?」

放行之后数字反而更难看

时间线不长,但每一步都踩在点上。3 月 11 日晚 22:40 切 DNS,新 CMS 接管全站;3 月 12 日补完 robots.txt,确认四个 AI 爬虫 UA 都能拿到 200;3 月 19 日上午,市场同事把引用数截图甩过来,数字是 0。

抓取与索引两道门主题图:爬虫过闸与拦截

我们查了三处:Nginx access log、站点地图的覆盖率报告、搜索引擎侧的抓取统计。日志里 GPTBot 的 200 命中数没掉,改版后一周日均有 210 次左右,比改版前还高一些——爬虫来得很勤快。

反常的是「已抓取、未索引」这个桶。改版前它稳定在 1.2k 上下,改版后一周涨到 4.6k,几乎是我们全站 URL 的一半。

抓取量正常、索引量归零,这个组合基本可以把 robots.txt 排除掉,问题在页面级或响应头级的索引指令上。

两道门的机制剖析

搜索引擎处理一个 URL,是两个独立动作。抓取(crawling)负责把字节下载回来,索引(indexing)负责把内容放进检索池。

robots.txt 只在第一道门起作用,它是一份自愿遵守的抓取授权声明。RFC 9309 里写得很明白:它不表达任何关于收录的意图,Allow 不等于「请收录我」。

第二道门由索引控制(indexing directive)管着,载体只有两个:HTML <head> 里的 meta robots,以及 HTTP 响应头里的 X-Robots-Tag。爬虫解析到 noindex,就把这个 URL 从检索池里剔出去。

noindex 有个容易被忽略的读取前提:爬虫必须先把 HTML 下载下来,指令才存在。你在 robots.txt 里对这个路径写了 Disallow,爬虫就不来抓,那行 noindex 谁也读不到。

这就是最别扭的地方——你想用 noindex 把页面撤下来,却用 Disallow 把读 noindex 的路堵死了。页面会以「仅 URL 索引」的形态赖在检索池里,标题和摘要取自外链锚文本,比正常收录还难看。

放到生成式引擎优化(Generative Engine Optimization, GEO)的语境里,这事更致命。AI 搜索拼答案时用的素材来自检索池,一个被 noindex 的页面连池子都进不去,robots.txt 写得再宽松都白搭。

三条指令到底管到哪一层

指令载体 生效位置 谁在遵守 管抓取还是管索引 常见误用
robots.txt(RFC 9309) 站点根目录纯文本文件 自愿遵守的爬虫 只管抓取授权 把 Allow 当成「允许收录」
meta robots HTML <head> 抓到 HTML 之后的解析器 管索引与链接跟随 改版后旧模板的 noindex 残留
X-Robots-Tag HTTP 响应头 同上,但由网关层下发 管索引,对任何 MIME 类型都生效 Nginx / CDN 统一加头,业务方不知情
索引快照与 site: 查询 搜索引擎侧 只是结果校验,不是指令 拿快照变化当修复成功的判据

顺带一句,X-Robots-Tag 在 PDF、图片这类没有 <head> 的资源上是绕不开的手段,后来我们把它单独收口管理,就是因为这类资源没法在 HTML 里声明。

排查是怎么分层的

我们把排查分成三层,从上往下剥:响应头、渲染后的 DOM、搜索引擎侧的索引快照。顺序不能反,因为越靠上层的问题越容易被下层现象盖住。

flowchart TD
    A[引用数归零] --> B{curl -I 看响应头}
    B -->|响应头带 noindex| C[定位 Nginx 或 CDN 层配置]
    B -->|响应头干净| D[curl 取正文 grep meta robots]
    C --> E[按域名拆分下发范围并 reload]
    D -->|命中 noindex| F[回溯模板 include 链]
    D -->|正文干净| G[抓渲染后 DOM 再比对一次]
    F --> H[改成按环境变量注入]
    E --> I[清空索引指令]
    H --> I
    I --> J[提交重新抓取并复核快照]
    J --> K[观察 7 到 14 天]

有个坑要提醒:curl -sI 发的是 HEAD 请求,个别网关对 HEAD 和 GET 下发的头并不一致。我们在第二台边缘节点上就遇到过 HEAD 干净、GET 带 noindex 的情况,所以两个方法都得跑。

第一层:先看响应头

依赖与环境:curl 7.68+,在能访问线上域名的跳板机上执行,域名已做化名处理。

# 第一层:只看响应头,确认网关层有没有偷偷下发 X-Robots-Tag
curl -sI https://www.example.com/solutions/erp
HTTP/2 200
content-type: text/html; charset=utf-8
x-robots-tag: noindex, nofollow
# ↑ 这行才是元凶之一,Nginx 层统一加的,业务方压根不知道
# 换 GET 再确认一次,防止 HEAD 与 GET 的头不一致
curl -s -D - -o /dev/null https://www.example.com/solutions/erp | grep -i robots
# 命中:x-robots-tag: noindex, nofollow
# 提醒:只看首屏 HTML 不够,前端渲染注入的 meta 还要用无头浏览器再验一次

老李看到这行的时候说了句「这不是我加的吗,去年压测的时候」。翻配置历史,果然是去年 8 月为了挡压力测试流量加的,一直没人摘。

事故配置和修复后的写法对比如下,依赖与环境:Nginx 1.20+,配置托管在 Git,改完走 nginx -t && nginx -s reload

# 事故写法:server 级统一加头,生产与预览站点共用一个配置片段
server {
    listen 443 ssl;
    server_name www.example.com;
    # 这行会让整站所有响应都带上 noindex,PDF 和图片也跑不掉
    add_header X-Robots-Tag "noindex, nofollow" always;
}

# 修复后:按域名拆分,生产域名不再下发任何索引指令
server {
    listen 443 ssl;
    server_name www.example.com;
    # 生产环境不加 X-Robots-Tag,索引控制权交回业务模板
    location / {
        proxy_pass http://cms_upstream;
    }
}

# 预览站单独一个 server 块,只在这里下发 noindex
server {
    listen 443 ssl;
    server_name preview.example.com;
    # 预览站才下发 noindex,避免测试内容被搜索引擎收走
    add_header X-Robots-Tag "noindex, nofollow" always;
}

改完记得验一遍真实响应头,别只看配置文件:

# 修复后 curl -sI 的响应头片段,域名已化名
HTTP/2 200
content-type: text/html; charset=utf-8
# 生产域名已无任何 X-Robots-Tag
cache-control: public, max-age=600
# 这行是边缘节点标记,与索引无关
x-cache: HIT from edge-sh-03

第二层:模板里的 meta 残留

依赖与环境:新 CMS 基于 Twig 模板,代码库本地 clone,grep 3.x。

<!-- 旧模板 legacy/public/header.html,被新 layout 直接 include 了 -->
<head>
  <meta charset="utf-8">
  <!-- 预览站时期为防止外网收录加的,改版时没人删 -->
  <meta name="robots" content="noindex,nofollow">
  <title>ERP 解决方案</title>
</head>

<!-- 修复后:按环境注入,只有预览域名才输出 noindex -->
<head>
  <meta charset="utf-8">
  <!-- 生产环境不输出任何 robots 指令,交由业务模板按需声明 -->
  {% if env == "preview" %}
  <meta name="robots" content="noindex,nofollow">
  {% endif %}
  <!-- 生产分支这里什么都不输出,绝不写 content="all" 之类的默认值 -->
  <title>ERP 解决方案</title>
</head>

新 CMS 的 layout 里写了 include 'legacy/public/header.html',旧模板那行 noindex 就跟着进了每一个页面。我们在 13 个模板文件里 grep,命中 4 个,全是改版时图省事直接 include 的旧文件。

第三层:比对索引快照

改完之后不能当场下结论。我们做了三件事:在抓取工具里提交重新抓取、把站点地图重新推送一遍、每天记录一次索引快照数字。

判据只有一个——「已抓取、未索引」这个桶要往下掉,不是快照里那条记录消失。有些页面被剔除后,快照里还会挂着带旧标题的壳子,看那个会误判。

对做 GEO 的团队来说,排查顺序其实应该反过来:先确认页面能进索引池,再谈内容怎么被 AI 摘引用。池子进不去,后面所有优化都是空转。

noindex 和 disallow 的死结

排查到这一步,还有个更隐蔽的组合问题值得单独拆开。

robots.txt meta 或响应头 爬虫实际行为 索引结果
Allow 无 noindex 正常抓取 正常索引
Allow noindex 抓了,读到指令 不索引,但持续抓取,白烧抓取预算
Disallow noindex 不来抓,指令读不到 仍可能以仅 URL 形态留在索引里
Disallow 无 noindex 不来抓 同上,且你失去了用 noindex 撤下的能力

拆这个死结的顺序是固定的:先把路径临时改成 Allow,让爬虫能读到 noindex,等索引里的存量被清干净,再决定要不要恢复 Disallow。顺序反了,noindex 就是一张废纸

stateDiagram-v2
    [*] --> 抓取授权: robots.txt Allow
    [*] --> 拒绝抓取: robots.txt Disallow
    拒绝抓取 --> 仅URL索引: 外链或站点地图带入
    拒绝抓取 --> 指令读不到: 页面从未被下载
    抓取授权 --> 解析指令: 读 meta robots 与 X-Robots-Tag
    解析指令 --> 剔除索引: 命中 noindex
    解析指令 --> 正常索引: 无限制指令

改完之后那十四天

口径先说明白:下面是我们自己跳板机日志和抓取统计里的观测数字,不是第三方报告,样本只有一个站。

时间 抓取命中(日均) 已抓取未索引 AI 引用条数(日均)
第 0 天(修完当天) 210 4.6k 0
第 3 天 190 3.1k 3
第 7 天 205 1.4k 17
第 14 天 198 0.9k 34

回涨不是线性的,第 3 到第 7 天那一段最陡。老李的原话是「像水管里的空气排干净了」。

容易翻车的几个点

把 noindex 当成实时开关用,是最常见的一个。它是抓取时才生效的指令,下发完还得等爬虫再来一趟,急不得。

CDN 缓存会把旧响应头一起缓存住。我们改完 Nginx 配置之后,边缘节点上还挂着两天的旧头,最后是手动刷新缓存才彻底干净。

预览站模板别直接拷生产。这次事故的根因就是这个,一行 include 就够把整站干掉。

往后看,索引控制权会往两头集中:一头是 HTTP 响应头,因为 AI 爬虫对非 HTML 资源的依赖越来越高;一头是结构化数据,决定进池之后被怎么理解。GEO 这块的活,会越来越像网关配置活,而不是文案活。

我们的收口做法很土但有效:所有索引指令只允许出现在两个地方——模板里的环境变量分支,以及一份受版本控制的网关白名单;CI 里加一条 grep 门禁,生产分支出现 noindex 直接失败。

你们那边如果也踩过类似的配置坑,评论区聊聊当时的排查路径,互相省点时间。

参考与延伸

  • Google 官方文档:阻断抓取与索引的区别 https://developers.google.com/search/docs/crawling-indexing/block-indexing
  • RFC 9309:Robots Exclusion Protocol https://www.rfc-editor.org/rfc/rfc9309
  • MDN:X-Robots-Tag 响应头 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/X-Robots-Tag
  • Google 官方文档:robots meta tag 与 X-Robots-Tag 规格 https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag

GEO, AI优化AIO, 网站索引排查, meta robots, noindex, X-Robots-Tag, AI爬虫

🤖
本内容由 AI 辅助生成,经人工校对审核;部分素材、资料来源于公开网络,仅作个人观点分享与交流使用,无任何商业侵权意图。若内容、图片、文字涉及您的合法著作权、版权权益,请联系本人,核实后将第一时间删除、修改相关内容。