搜索全站
Google SEO 9 分钟阅读

WordPress 站内搜索结果页要不要被索引?noindex 正确做法

站内搜索页被索引会制造大量垃圾页面。本文讲清 Google 对搜索结果页的官方建议,给出 WordPress 用 wp_robots 输出 noindex 的代码与 robots.txt 配合方案。

U
UFO_PF 2020-07-27 · 阅读 9 分钟
Wo GOOGLE SEO
阅读提示
本文约 3,530 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:几万条 ?s= 页面混进了索引库

打开 Search Console 的”网页”报告,有时会发现索引量比实际文章数多出好几倍,点开一看全是 /?s=关键词 或 /search/关键词 这样的 URL。这些页面内容是由用户或爬虫任意组合关键词生成的,标题千奇百怪,正文可能是”未找到结果”,也可能混杂了几十条摘要片段。它们既没有搜索价值,又会消耗大量抓取预算,让真正重要的新文章迟迟不被抓取。

Google 官方对这类页面的态度很明确:站内搜索结果页不应被索引。官方帮助文档给出的建议是对搜索结果页使用 noindex,而不是放任其被收录。问题在于,WordPress 默认并不会给搜索页加 noindex,很多主题也没处理,于是这些页面就顺理成章地进了索引库。

原理分析:为什么 noindex 优于 robots.txt 屏蔽

很多人的第一反应是在 robots.txt 里写 Disallow: /?s=。这有两个隐患:第一,robots.txt 只阻止抓取,不阻止索引——如果这些 URL 被外部链接指向,Google 仍可能在没有内容的情况下把它们编入索引,形成”无内容的索引页”;第二,Disallow 会让 Google 无法看到页面里的 noindex 指令,指令永远不生效。

方案 能否抓取 能否索引 适用
什么都不做 能 能 不推荐
robots.txt Disallow 否 可能索引 仅配合用
noindex 响应头/标签 能 否 推荐
noindex + Disallow 否 否(指令可能读不到) 需谨慎

正确做法是允许抓取、输出 noindex,让 Google 抓到页面后读到指令并放弃索引;确认索引清除后,再考虑是否用 robots.txt 减少抓取浪费。

另外要区分两类搜索页:一是 WordPress 原生的 /?s=;二是主题或插件(如 WooCommerce 的产品搜索、FacetWP、Search & Filter)生成的筛选页 /?color=red&size=m。筛选参数页的体量往往比原生搜索页大得多,是更需要处理的重灾区。参数页面建议结合 canonical 指向无参数版本一并处理。

保姆级实操

步骤 1:确认当前状态。 在 GSC 里搜索 site:你的域名/?s=(或用”网页”报告筛选含 s= 的 URL),统计已索引数量;再打开一个搜索页查看源码,确认有没有 <meta name="robots" content="noindex">。

步骤 2:用 wp_robots 过滤器输出 noindex。 WordPress 5.7 起内置 wp_robots() 输出 robots 元标签,通过 wp_robots 过滤器追加指令即可,无需手写 wp_head。

<?php
// 搜索结果页输出 noindex、nofollow(WordPress 5.7+)
add_filter('wp_robots', function ($robots) {
    if (is_search()) {
        $robots['noindex']  = true;
        $robots['nofollow'] = true;
        $robots['noarchive'] = true;
    }
    return $robots;
});

若站点还在用旧版本 WordPress,可在 wp_head 里手工输出:

<?php
// 兼容旧版本:直接输出 meta 标签
add_action('wp_head', function () {
    if (is_search()) {
        echo '<meta name="robots" content="noindex,nofollow,noarchive">' . "\n";
    }
}, 1);

步骤 3:处理带参数的筛选页。 对指定参数组合输出 noindex,同时保留 canonical 指向无参数版本。

<?php
// 对带筛选参数的归档页输出 noindex,并把 canonical 指向干净 URL
add_filter('wp_robots', function ($robots) {
    $params = ['color', 'size', 'brand', 'min_price', 'max_price'];
    foreach ($params as $p) {
        if (isset($_GET[$p])) {
            $robots['noindex'] = true;
            break;
        }
    }
    return $robots;
});

add_filter('wpseo_canonical', function ($canonical) {
    if (is_post_type_archive('product') && !empty($_GET)) {
        return get_post_type_archive_link('product'); // 指向无参数版本
    }
    return $canonical;
});

步骤 4:确认索引已清除后再考虑 robots.txt。 只有在 GSC 确认这些 URL 已全部移出索引后,才适合加抓取限制,避免指令读不到。

# robots.txt —— 仅在 noindex 生效一段时间后再考虑添加
User-agent: *
Disallow: /?s=
Disallow: /search
Allow: /

注意 Disallow: /?s= 对路径形式 /search/xxx 无效,需按实际 URL 形态分别写。

步骤 5:从 sitemap 中排除。 Yoast SEO、Rank Math 默认都不会把搜索页写进 sitemap,但自定义 sitemap 时要确认没有包含搜索路由。

步骤 6:提交移除与复查。 在 GSC 的”移除”工具中对已索引的搜索 URL 提交临时移除,随后观察”网页”报告中的数量变化。搜索页与抓取预算的关系,可配合 Google 抓取预算优化 一起分析。

常见踩坑

  1. 案例: 某站只加了 Disallow: /?s=,没有输出 noindex。半年后 GSC 显示 1.2 万个 ?s= URL “已编入索引”,且因无法抓取而全部无标题无描述,占据索引报告的绝大多数。补上 noindex 并等四周后,索引数才逐步回落。
  2. 在 robots.txt 屏蔽后又提交”移除 URL”,Google 读不到页面就无法执行移除请求,操作必然失败。顺序必须是先 noindex、后考虑 Disallow。
  3. 过滤器写成 is_search() 却挂在 wp_footer,输出位置不对导致 meta 标签出现在 <body> 中,指令失效。
  4. 只处理 /?s=,忽略插件生成的 /?filter=xxx 参数页,问题只解决了一半。
  5. 给搜索页加 noindex 的同时又加了 follow,爬虫顺着页面里的链接继续抓,浪费预算。搜索页应 noindex,nofollow 同时使用。
  6. 用 header() 发送 X-Robots-Tag 却与插件输出的 meta 冲突,出现一处 noindex、一处 index 的矛盾,Google 会取最严格的那个,但排查会很混乱。
  7. 把搜索结果页做成”热门搜索聚合页”想蹭流量,内容却是自动生成的摘要堆叠,容易被判定为低质量门页。

总结

判断标准:任何由用户输入或参数组合动态生成的页面,只要内容没有人工编辑价值,就不应被索引。行动顺序是——先确认已索引数量;用 wp_robots 给 is_search() 和指定参数输出 noindex,nofollow;参数页补 canonical 指向干净 URL;确认索引清除后再考虑 robots.txt;最后用 GSC”移除”工具加速清理。做完这一步,你会发现抓取预算明显宽裕,新文章的收录速度也会变快。相关索引规则还可参考 robots.txt 配置教程。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。