本文约 4,813 字,预计阅读 13 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:site.com/sitemap_index.xml 的背后,藏着三套互不相干的规则
一个典型的 WordPress 站点运行两年后,很可能同时存在以下几份站点地图:
- WordPress 核心自带:
wp-sitemap.xml(WP 5.5+ 引入),索引里包含 posts、pages、taxonomies、users - SEO 插件的:Yoast 是
sitemap_index.xml,Rank Math 也是sitemap_index.xml(两者文件名相同会直接冲突) - 主题自带的:部分商务主题(比如某些 Themeforest 主题)自己注册了
/sitemap.xmlrewrite - 缓存/ era/hosting 面板自带的:有些主机控制面板会额外生成静态 sitemap
这不是洁癖问题。多份 sitemap 会带来三个实打实的后果:第一,GSC 里”已发现的网址”和”索引”迟迟不上涨——因为搜索引擎要在多份地图里去重,且其中可能有 404 的条目;第二,权重 signals 分散,同一 URL 在不同 sitemap 里的 lastmod 不一致会让引擎困惑;第三,GSC 提交数和实际抓取量不匹配,排查起来极其费时。
本文讲怎么稳扎稳打地把多份回归到一份。
原理分析:区分三层的”Sitemap”概念
| 层级 | 位置 | 谁生成 | 如何关闭 |
|---|---|---|---|
| 核心 XML 站点地图 | /wp-sitemap.xml |
WP 核心 WP_Sitemaps 类 |
remove_action/wp_sitemaps_enabled 过滤器 |
| 插件 sitemap | /sitemap_index.xml |
Yoast / Rank Math / SEOPress / All in One SEO | 插件后台开关 |
| robots.txt 里的声明 | /robots.txt 的 Sitemap: 行 |
由上述任一 réaliser 自动添加 | 由谁生成就改谁 |
| 主题/自定义 | 各种 URL | 主题的 rewrite 规则 | 主题选项或 remove_rewrite |
三条必须记住的技术事实:
第一,核心 sitemap 用 wp_sitemaps_get_server 注册 provider。 想精确控制某一类内容是否进入核心地图,用 wp_sitemaps_add_provider / wp_sitemaps_enabled 过滤器。
第二,robots.txt 是虚拟的。 WordPress 通过 do_robots() 动态输出 robots.txt,因此服务器上不会有 robots.txt 文件。如果根目录存在真实 robots.txt 文件,它会优先于 WordPress 生成的那份,导致你在后台改了 sitemap 声明却完全不生效——这是非常高频的坑。
第三,Sitemap: 指令建议写成绝对 URL 且放在 robots.txt 末尾。 另外注意:Google 支持 robots.txt 里声明,Bing/百度同样支持;但百度站长平台更推荐直接在平台后台提交。
保姆级实操
步骤 1:先清点所有 sitemap
for u in wp-sitemap.xml sitemap_index.xml sitemap.xml xmlsitemap.xml post-sitemap.xml; do
code=$(curl -s -o /dev/null -w "%{http_code}" "https://example.com/$u")
size=$(curl -s "https://example.com/$u" | wc -c)
echo "$u -> HTTP $code, ${size} bytes"
done
同时看 robots.txt:
curl -s https://example.com/robots.txt
把输出里的每一行 Sitemap: 记下来,它就是你接下来要统一的目标。
步骤 2:关闭 WordPress 核心自带的 wp-sitemap.xml
两种取舍:
// A:彻底关闭核心 sitemap(装了 Yoast/Rank Math 时推荐)
add_filter( 'wp_sitemaps_enabled', '__return_false' );
// B:保留核心地图,但剔除 users 归档(避免泄露作者用户名)
add_filter( 'wp_sitemaps_add_provider', function( $provider, $name ) {
if ( 'users' === $name ) {
return false;
}
return $provider;
}, 10, 2 );
步骤 3:处理 Yoast / Rank Math 的同名冲突
Yoast 与 Rank Math 都占用 /sitemap_index.xml。同时启用会以先注册 rewrite 规则者胜出,另一方的 URL 会 404。必须二选一:
- 保留 Yoast:「Yoast SEO → Settings → Features」→ 关闭 Crawl optimization 里的 “Remove core search”? 不需,重点是「Rank Math → Sitemap Settings → 关闭」。
- 保留 Rank Math:「Yoast SEO → 功能 → XML 站点地图」关闭。
用代码核验是否已关闭:
wp option get rewrite_rules | grep -o 'sitemap' | head
步骤 4:清理残留的 rewrite 规则
插件卸载后旧的 rewrite 规则会留在 wp_options 的 rewrite_rules 里,导致 URL 仍然 200 但内容为空:
# 刷新 rewrite 规则(等价于后台「设置→固定链接→保存」)
wp rewrite flush --hard
wp cache flush
步骤 5:统一 robots.txt 里的 Sitemap 声明
不要同时依赖多个插件去写这行,容易互相覆盖。直接在主题的 robots_txt 过滤器里一次性定义:
add_filter( 'robots_txt', function( $output, $public ) {
if ( '0' === (string) $public ) {
return $output; // 站点被设为不公开时保持原样
}
$lines = explode( "\n", $output );
$lines = array_filter( $lines, function( $line ) {
return stripos( $line, 'Sitemap:' ) === false; // 先移除别人加的
} );
$lines[] = 'Sitemap: ' . home_url( '/sitemap_index.xml' );
return implode( "\n", $lines ) . "\n";
}, 99, 2 );
优先级设 99 保证最后一个执行,把你自己的声明写进去。
步骤 6:处理”真实 robots.txt 文件抢跑”
# 检查站点根目录是否有物理 robots.txt(有则 WordPress 的钩子无效)
ls -la /var/www/example.com/robots.txt
如果存在需要处理:要么删掉物理文件让 WordPress 接管,要么接受物理文件为唯一来源并在里面手动写好 Sitemap: 行(意思是后续自动化失效,每次改 sitemap 都得手动改文件)。推荐前者。
步骤 7:在 GSC 与百度平台重新提交
清理完毕后,在 Google Search Console 的「站点地图」里删除旧的、只提交唯一的 sitemap_index.xml;百度站长平台同样处理。
常见踩坑
- 站点设成了”建议搜索引擎不索引本站点”:「设置 → 阅读」的那个勾选会让 robots.txt 输出
Disallow: /。很多站长迁移后忘了取消。这是收录为零的第一大原因。 - HTTP/HTTPS 或 www 的 canonical 不一致:sitemap 里的 URL 是
http://而站点 canonical 是https://,GSC 会报”sitemap 中的网址与站点不匹配”。确保home_url()返回的是最终形态(is_ssl()感知)。 - 案例:某外贸站点运营三年,GSC 里 sitemap 一直显示”已发现 2,340 个网址,但最新读取一直失败”。排查发现:站点曾经装过一个 All in One SEO Pack 并卸载,但它写入根
robots.txt的两行Sitemap:指向了早已失效的sitemap_index.xml?ver=2与一篇 404 的 post-sitemap.xml。更惨的是这份 robots.txt 是物理文件,其后所有插件在后台做的 sitemap 配置全部无效。清理物理文件 +wp rewrite flush+ 重新提交之后,两周内新索引文章 +187 篇。教训:robots.txt 与 sitemap 这类”看不见的配置”要列入迁移/交接清单。 wp_sitemaps_enabled关不掉 Yoast:两者是独立系统,这个过滤器只管核心的wp-sitemap.xml。- CDN 缓存了旧的 robots.txt:robots.txt 也会被 CDN/APO 缓存,改完后记得 purge。
- 同一份 sitemap 出现 404 子项:trash 里的文章、被
noindex的 URL 会被插件保留在 sitemap 中。Yoast 会自动排除 noindex 的条目,但有些主题地图不会。 <lastmod>每次构建都变:部分插件用time()而不是文章真实修改时间,导致搜索引擎认为全站都在更新,抓取预算被浪费。用get_the_modified_date( 'c', $post )才是正确取值。- Nginx 自身 rewrite 抢了
/sitemap.xml:有些一键安装包自带伪静态规则重写 sitemap 到某个静态文件。检查 Nginx conf 里location = /sitemap.xml。
延伸阅读:XML Sitemap 拆分策略、robots.txt 配置详解
总结
统一 sitemap 只需要做对四件事:①清点(用上面的循环脚本扫所有常见路径 + 看 robots.txt);②二选一(Yoast 与 Rank Math 只能留一个,另一个的 sitemap 开关必须关);③关核心(wp_sitemaps_enabled 或至少剔除 users provider);④回 robots.txt 收拢为一行,并检查是否存在物理 robots.txt 文件抢跑。完成后在 GSC 重提、观察 1–2 周的”已发现网址”变化,这是唯一可靠的验收指标。
