← 返回 打印的日志表单铺在黑色书桌上,黄铜灯下,一行用红笔圈出

Google 拒绝读取六个月的网站地图,以及 14 秒的修复方案

SEO、AEO 与 GEO

如果 Google Search Console 显示你的网站地图索引状态为成功,但发现的页面数为零,子网站地图无论重新提交多少次都停留在"无法获取"状态,那你可能看的不是服务器问题。你看的是 Google 网站地图调度程序内部的单个 URL 退避。最快的证明方法是在略微不同的 URL 下重新提交相同的文件,然后观察会发生什么。

那个诊断用了我六个月、五次独立审计和四个不同的 AI 模型。最后解决问题的测试只用了 14 秒。

关键要点:网站地图索引可以报告成功,但其中的每个子网站地图对 Google 来说都是不可见的。如果你的边缘日志显示 Google 机器人对"无法获取"的子网站地图没有任何请求,那么失败是在 Google 一方,不是你这方。在版本化 URL(如 /sitemap/0.xml?v=20260815)下重新提交相同的文件可以绕过退避,在几秒内处理。

"成功"实际上在报告什么

这个网站是 Deluxe Astrology,我父母的吠陀占星平台,也是我运营的最大项目:跨越 30 种语言的大约 240,000 个 URL,从 Supabase 发布,并作为有 63 个子网站地图的网站地图索引提供。我在 Deluxe Astrology 项目页面上介绍了其背后的架构。

索引页面数周来一直在下滑。印象数在 6 月末突然崩溃。而那个唯一的工作就是为 Google 提供新 URL 列表的系统显示了绿色勾号。

在 Search Console 中打开网站地图索引,它说"网站地图索引处理成功"。点进去,网站地图读取表显示 0-0 / 0。Google 在三周内获取了索引三次,正确地将其解析为索引,但没有注册其任何子网站。没有一个子网站地图曾被获取过。当我直接提交其中三个时,它们停留在"无法获取"状态好几小时。

这就是陷阱。网站地图索引上的状态是关于索引文件本身的陈述。它告诉你 XML 已解析,子 URL 格式良好。它对 Google 是否真的去读取它们一无所知。这种区别隐藏在一个大多数人从不滚动到的表格中,对于任何大到需要网站地图索引的网站来说,这就是全部要点。

服务器上的一切都检查无误,五次独立验证

如果你碰到过"无法获取",你知道接下来的一小时会怎样。你 curl URL。你检查 robots.txt。你检查防火墙。你检查 CDN 缓存。你运行 URL 检查中的实时测试。一切都很顺利。所以你告诉自己这个经典的 Search Console 谎言:它只需要时间,24 到 72 小时后再查看。

在接下来的几个月里,这成为了一项真正全面的调查,不仅仅是我。我通过几个前沿模型作为独立审计员运行了这个问题:Claude、Kimi、GLM 和几个定制代理,每个都可以访问代码库、Search Console 数据和边缘日志。我之前写过关于同时运行多少个 AI 模型才真正值得的文章,这个案例对此的测试最严苛。

他们在几乎所有事情上都意见一致,在几乎所有事情上也都是正确的:

  • 实时网站地图索引提供了有效的 <sitemapindex>,包含全部 63 个子网站地图、正确的内容类型、无字节顺序标记、无跨主机 URL。
  • 每个子网站地图都提供了有效的 <urlset>,含有预期的 URL 计数。
  • Googlebot通过URL检查工具对索引和子站点地图的实时抓取返回了真实的XML。"网址可供Google访问。"
  • 边缘日志显示实际的Googlebot请求到达索引并从缓存返回200状态码。
  • robots.txt、中间件、重定向或CDN配置都没有涉及站点地图路径。

一个早期的错误是真实存在的,已经被修复。几个月前为了对抗一个令我的托管账单飙升的机器人农场而在WAF上添加的每IP速率限制,曾经一度挑战了爬虫流量。那条规则已被纠正。修正后,每次审计都得出了相同的结论:服务器端清洁无误,Google需要时间,24到72小时后再检查。

五次审计。相同的判断。相同的建议。数字没有变化。

真正的问题出在缺失上,而不是错误。

令人不适的事实隐藏在边缘日志中,在那些不存在的东西里。提交三个子站点地图后,没有任何Googlebot对它们的请求。既没有被允许的请求,也没有被挑战的请求,更没有被拒绝的请求。Google不是在抓取子站点地图时失败。Google是选择不尝试。

你无法从服务器那边诊断这个问题,这在本质上是不可能的。没有任何东西到达服务器来检查。标准工具包中的每个工具都是为了解释出了问题的请求而构建的,但这里没有请求。这是日志文件分析通过遗漏而非证据来解决的唯一类问题:你去寻找这些记录,答案就是空的结果集。

Search Console的实时测试让情况更糟,因为它绕过了做出选择的任何调度程序。它按需从不同的代码路径抓取,并为站点地图子系统永远不会入队的网址愉快地报告"可用"。绿色的实时测试不是证明站点地图管道会触及该文件的证明。

API讲述了UI不愿说的真话

Search Console Sitemaps API提供了第一个诚实的信号。UI显示"无法抓取",这看起来像是一个有原因的失败。API返回isPending: trueerrors: 0,完全没有lastDownloaded时间戳。

这些是不同的声明。"无法抓取"意味着一个失败的尝试。isPending且零错误意味着从未尝试过。六个月的调试都针对一个根本不存在的失败。

如果你在大规模运行任何东西,在需要API之前就把它连接好。它只是一个OAuth范围和几行代码,却是状态字符串的区别——一个为了安心而设计的字符串,与记录的实际状态。这就是我在Claude Code SEO audit workflow中大量依赖它的原因。

对照实验

我没有进行第六次审计,而是进行了一个对照。

首先是基线。我提交了一个Google从未见过的站点地图,这是网站一个侧边部分的小站点地图。它在提交后34秒内被下载并处理。所以管道是健康的,主机是可访问的,Google现在愿意从这个域获取站点地图。

然后是真正的测试。我重新提交了一个卡住的子站点地图,字节上完全相同,由同一服务器上的同一路由提供,只有一个区别:末尾的查询字符串。/sitemap/0.xml?v=20260815

提交Google的状态处理时间
`/sitemap/0.xml`(原始)2小时30分钟后待处理从不
新网站地图,之前从未提交过已处理34秒
`/sitemap/0.xml?v=20260815`(相同文件)已处理,2,187个网址14秒

相同文件。相同服务器。相同字节数。不同的字符串。一个在两个半小时内一直未被读取且仍在计数,另一个在14秒内被读取。

这就是全部诊断结果,也是我一直坚持认为受控测试胜过再次验证的原因。每次审计都确认了服务器的事实。没有一次改变了唯一重要的输入。

实际发生的事情

Google的网站地图系统对那63个确切的网址实施了按网址失败退避。

几个月前,每次读取索引都会在几秒内从单个Google IP触发63个子项获取的突发。这是索引的正常Googlebot行为:它读取父项,然后立即获取子项。WAF上按IP的速率限制(按平均人类流量调整),看到来自一个地址的63个请求突发,就按其配置方式处理。它进行了质询。每个周期。持续了数周。

单个索引请求本身总是能勉强通过,因为一个请求不是突发。这就是为什么索引继续显示"成功",而其子项从未出现过。该规则完全针对我最需要Google读取的网址,而将报告它们的那个网址完全保留了下来。

修复防火墙并没有清除Google对已失败网址的记忆。它只是停止了创建新的失败。这63个特定字符串上的退避在修复后仍然存在,没有任何等待方式能在我可以观察的时间范围内使其过期。

修复方案:63次提交,零次部署

通过Search Console API,我使用版本查询字符串重新提交了所有63个子项。大约两分钟内,每一个都被获取和处理:155,545个网址已在Google注册,零个错误,零个警告。发现的页面,在半年内显示为零,在我观看时被填充。

耐用的修复是下一个版本中的两行代码更改:让网站地图索引发出版本化的子网址,这样索引和robots.txt指向Google愿意读取的网址。只要生成逻辑改变,就增加版本令牌,你就免费获得了一个清洁的缓存破坏机制。

一个诚实的警告。索引不等于发现。Google在数月不信任后以缓慢速度抓取此主机,155,000个网址在一周内不会被扫过。发现再次运作是前提条件,而不是结果。如果你的抓取预算已经很紧张,修复网站地图是工作的起点。

为什么五次审计都得出了错误答案

这是我一直回到的部分。

这些模型在验证方面表现出色。给定关于内容类型、缓存标头、robots指令或中间件的声明,它们准确检查并诚实报告。但它们中没有一个会主动提议以不同名称提交相同文件来看会发生什么。

对共同盲点的汇聚看起来完全像共识。五个审计员以相同的假设读取相同的证据,即获取失败意味着获取尝试,将产生五个有信心的协议和零进展。这种协议感起来像是确认。它实际上是审计员之间的相关性,而不是审计员与现实之间的相关性。

打破僵局的不是另一次审计。而是决定六个月的"等待72小时"是一个假设而不是计划,并设计一个测试,其中唯一的变量是网址字符串。这是人的工作,我不认为它很快就会停止。

我从中吸取的五条规则

  • 站点地图索引的成功与否取决于索引文件本身,而非其子文件。滚动到"已读站点地图"。如果显示零,绿色勾号只是装饰。
  • UI 中的"无法获取"在 API 中意味着"尚未处理"。阅读 API。isPendinglastDownloaded 才是你真正需要了解的,而 UI 两者都不显示。
  • Google 对你的基础设施错误的记忆比你本人更久。困扰爬虫几周的速率限制可能会让特定网址在规则消除后长时间处于退避状态。等待不能可靠地清除它。版本化网址可以。
  • 为爬虫突发流量而非平均流量设置速率限制。一次索引读取会在几秒内从一个 IP 触发 N 次子文件获取。任何低于 N 的每 IP 限制都会恰好困扰你最需要 Google 读取的网址,而索引本身通过并报告成功。
  • 当多个模型都认为服务器状况良好且你应该等待时,它们大概率是对服务器的判断正确,对等待的判断错误。运行对照测试,而非第六次审计。

如果你认为遇到了同样的问题

按顺序完成这些步骤。大约需要十五分钟,能明确区分服务器问题和 Google 端的退避。

  • 在 Search Console 中打开站点地图索引,查看"已读站点地图"计数,而非状态。健康索引上零个子文件被读取是典型特征。
  • 通过 Search Console API 提取相同的站点地图。记下每个站点地图的 isPendingerrorslastDownloaded
  • 搜索你的边缘服务或 CDN 日志,查找过去 30 天内发往特定子路径的 Googlebot 请求。完全没有任何状态的请求意味着问题不在你的服务器上。
  • 提交一个 Google 从未见过的全新站点地图网址。如果它在一分钟内处理,你的主机和管道状况良好。
  • 用版本查询字符串重新提交一个卡住的子文件。如果它被处理而纯 URL 没有,你同时得到了答案和解决方案。
  • 根据突发行为而非平均值审计你的 WAF 速率限制,防止退避重建。然后检查大型网站的其余索引编制基础知识。

所有这些的参考资料来自 Google 自己的站点地图构建和提交指南,以及 sitemaps.org 协议——仍然是仅有的两份重要文档。两者都未提及每 URL 退避,这就是为什么花了这么长时间。

如果你运营超过 100,000 个网址的网站并遇到同样的问题,这正是我的工作内容:大型网站的技术 SEO,包括站点地图从形式变成整个分发渠道的程序化 SEO 构建。我有 API 脚本、诊断流程和解决经验。

FAQ

为什么我的站点地图索引显示"成功"但发现的页面数为零?

因为状态仅指索引文件本身。Google 解析了你的 <sitemapindex> 并找到格式正确的子网址,这就是"成功"声称的全部。它是否随后获取了那些子文件在"已读站点地图"表中单独报告。有效索引上零个被读取意味着子文件从未被处理,绿色勾号没有告诉你任何有用的信息。

Search Console 中的"无法获取"实际上是什么意思?

没有听起来那么严重。在 Search Console API 中,同一站点地图通常返回 isPending: trueerrors: 0 和无 lastDownloaded 值,这意味着 Google 还未尝试获取,而非尝试后失败。在你花时间调试一个可能根本不存在的失败之前,先查看 API。

我应该等多久才能认定网站地图确实卡住了?

Google愿意读取的网站地图通常在几秒到几分钟内处理,而不是几天。如果子网站地图已挂起超过24小时,而同一主机上的全新网站地图URL立即处理,那么继续等待不是策略。改为运行版本化重新提交测试。

在网站地图URL中添加查询字符串会导致重复内容或其他SEO问题吗?

不会。网站地图是一个发现文件,不是可索引页面,其中的URL保持不变。Google将/sitemap/0.xml/sitemap/0.xml?v=20260815视为两个不同的网站地图资源,这正是你利用的属性。在索引和robots.txt中指向版本化URL,这样就有了一个规范集合。

WAF速率限制会破坏网站地图发现,但不会破坏其他任何东西吗?

会的,这正是让它难以发现的原因。读取网站地图索引会在几秒内从单个Google IP触发大量子请求,所以按IP设置的速率限制(针对人工流量大小)会挑战子请求,而单个索引请求通过。网站上的其他所有内容,包括实时URL检查测试,都能完美工作。

修复网站地图会立即恢复丢失的展示次数吗?

不会。发现和索引是两个独立的阶段。获取155,000个URL已注册会恢复管道输入,但已失败数月的主机上的爬取速率会逐步恢复,索引决策则在爬取之后进行。预期需要数周时间,可以利用这段时间确保被发现的页面值得索引。

← 返回