本文约 3,319 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:屏蔽了半年,页面还在搜索结果里
最常见的求助场景是这样的:站点有一批内部用的页面(活动落地页、测试页、员工后台入口),不希望被搜索到。站长在 robots.txt 里加了 Disallow: /internal/,半年后发现这些页面依然出现在搜索结果中,标题正常、只是没有摘要,点击进去还能打开。于是又去 GSC 提交移除,移除期结束后又回来了。
根结在于搞错了工具的用途:noindex 是索引指令,robots.txt 是抓取指令。两者作用在不同阶段,用错就变成了“互相拆台”——robots 屏蔽让 Google 读不到 noindex,noindex 又被永远无法读取。
原理分析:三条指令作用在三个不同阶段
| 指令 | 作用阶段 | 生效条件 | 副作用 |
|---|---|---|---|
robots.txt Disallow |
抓取前 | 立即生效(缓存刷新后) | Google 读不到页面内容,也读不到 noindex |
meta robots noindex |
抓取后、索引前 | 必须被抓取到才会生效 | 需要放开抓取 |
X-Robots-Tag 响应头 |
抓取后、索引前 | 同 noindex,但可用于非 HTML 资源 | 需服务器/应用层支持 |
关键结论:想让一个页面不进索引,唯一可靠的做法是允许抓取 + 输出 noindex。 robots.txt 屏蔽只适合“不想浪费抓取预算”的场景,不适合“不想被收录”的场景。
还有几个容易混淆的点:
noindex 与 nofollow 可以组合使用,也可以单独使用。noindex, follow 表示“不索引这个页面,但仍然顺着本页链接继续抓取”——这是给低价值但内部链接重要的页面用的。
noindex 对非 HTML 资源无效(PDF、图片),这类资源要用 X-Robots-Tag 响应头。
nofollow 不是“不传递权重”的硬开关,Google 早已把它降级为提示信号(hint)。
noindex 会随时间失效的说法是错的,但如果页面同时被 robots 屏蔽,noindex 永远不会被读到,这才是它“失效”的真正原因。
移除需要时间:Google 抓到 noindex 后才会把页面从索引里剔除,通常需要几天到数周。如果需要紧急处理,用 GSC 的移除工具争取时间(见 GSC 移除工具的使用场景)。
保姆级实操
步骤 1:先确认页面当前是否被 robots 屏蔽。 用 URL 检查工具查,看 robotsTxtState。如果是 DISALLOWED,第一步是放开 robots,让 Google 能读到页面上的 noindex。
步骤 2:在 WordPress 里按条件输出 noindex。 推荐用响应头方式,这样对非 HTML 资源同样有效,且不依赖主题模板。下面这段代码用 wp_headers 过滤器按条件添加 X-Robots-Tag:
// 按条件输出 X-Robots-Tag:登录页、搜索结果页、内部活动页不索引
add_filter( 'wp_headers', function ( $headers ) {
$noindex = false;
if ( is_search() || is_404() ) {
$noindex = true;
}
// 内部活动落地页:以 /internal/ 开头
if ( str_starts_with( $_SERVER['REQUEST_URI'] ?? '', '/internal/' ) ) {
$noindex = true;
}
// 分页第 2 页之后不索引,但仍允许抓取链接
if ( is_paged() ) {
$noindex = true;
}
if ( $noindex && ! is_user_logged_in() ) {
$headers['X-Robots-Tag'] = 'noindex, follow';
}
return $headers;
} );
步骤 3:不需要响应头时,用 meta 标签。 在主题的 wp_head 里按条件输出,效果等价,但只作用于 HTML 文档:
add_action( 'wp_head', function () {
if ( is_category() && ! is_paged() ) {
return; // 分类第一页保持可索引
}
if ( is_date() || is_author() || is_tag() ) {
echo '<meta name="robots" content="noindex, follow" />' . "\n";
}
}, 2 );
步骤 4:验证输出确实生效。 用命令行看响应头,不要只看页面源码:
# 确认 X-Robots-Tag 是否真的出现在响应头里(注意 CDN 与缓存层可能剥离自定义头)
curl -sI https://www.example.com/internal/promo-2026/ | grep -i "x-robots-tag"
# 同时确认 robots.txt 没有屏蔽该路径
curl -s https://www.example.com/robots.txt
步骤 5:等待并跟踪。 加完 noindex 后,在 URL 检查工具里点「请求编入索引」(其实是请求重新抓取),等 Google 读到指令后页面会被剔除。在索引报告的「已按 noindex 标记排除」分组里能看到进度。
步骤 6:把“临时”与“永久”分开。 临时不想被收录用 noindex;永久不存在的内容应返回 404 或 410;需要紧急下线的,先用移除工具再补 noindex。
常见踩坑
- robots 屏蔽 + noindex 同时使用。 经典死循环:
noindex永远读不到。 - 用
nofollow代替noindex。nofollow管的是链接,不管索引。 - 在页面里写
noindex却又把该 URL 放进 sitemap。 自相矛盾的声明,会降低 sitemap 可信度。 - CDN 剥离了自定义响应头。 加完
X-Robots-Tag后必须用curl -I验证,不能假设生效。 - 缓存插件缓存了带 noindex 的版本。 需要被索引的页面被错误地缓存了 noindex 版本,全部掉出索引。
- 用 JS 动态插入 meta robots。 Google 需要解析 DOM,可靠性差,务必服务端输出。
- 案例: 一个电商站为了“防止重复”,在 robots.txt 里屏蔽了全部带
?variant=的 URL,同时在页面上加了noindex。一年后清理时发现,这 3000 多个 URL 全部以无摘要形式留在索引里,占了该站 GSC 展现量的 18%。改为放开 robots、只保留noindex+ 自引用 canonical 后,两个月内这些 URL 才陆续退出索引。这个错误在电商站里几乎人手一份。
总结
记住一句话就够了:要不被收录 → 放开抓取 + noindex;要不被抓取 → robots 屏蔽(但它不解决收录问题)。实现上优先用服务端输出的 X-Robots-Tag(覆盖非 HTML 资源、不受主题更换影响),其次才是 meta 标签;加完必须用 curl -I 验证响应头真实存在,并确认 CDN 没有剥离。判断标准:URL 检查工具里 robotsTxtState 为 ALLOWED 且索引状态为「已按 noindex 标记排除」,这才说明配置真的生效了。
