Sitemap 超过 5 万 URL:用 sitemap index 切分

单个 sitemap.xml 上限是 5 万 URL、未压缩 50 MB。Search Console 报 "Couldn't fetch" 或者只读前 5 万条。怎么正确切分并重新提交。

你从内容集合一把生成了 sitemap.xml。文件 18 MB,7.3 万条 URL。Search Console 要么报 Couldn't fetch,要么解析到的数量刚好卡在 50,000——读到上限就把剩下的悄悄丢了。索引位置 5 万之后的页面,再也不会从 sitemap 路径被发现。

最快修法:单文件上限是硬的,别再纠结怎么把一个文件压小。把 URL 切成多个子 sitemap,每个 <= 50,000 条(建议 2.5 万),再写一个 sitemap index 文件把它们列出来,把这个 index 放在 robots.txt 原本指向的那个 URL 上(/sitemap.xml),然后在 Search Console 重新提交 index。下面讲怎么切、怎么命名、怎么验证、怎么确认 Google 处理了每个子文件。

硬上限(2026 年 6 月核实)

sitemaps.org 协议写得很明确,Google 全部严格执行:

上限数值作用对象
每个 sitemap 的 URL 数<= 50,000<loc>单个 urlset 文件
每个 sitemap 的大小<= 50 MB(52,428,800 字节)未压缩单个 urlset 文件
每个 index 的子 sitemap 数<= 50,000单个 sitemapindex 文件
每个 index 的大小<= 50 MB 未压缩单个 sitemapindex 文件
每个 Search Console 资源的 sitemap 数最多提交 500 个整个资源

两件事最坑人。第一,gzip 用于传输没问题,但 Google 拿 未压缩 大小去比 50 MB 上限,所以一个 6 MB 的 .gz 解压成 70 MB 照样失败。第二——这一点跟很多人的直觉相反——只有 <loc> 算进 5 万上限。嵌在 <url> 块里的 <xhtml:link rel="alternate" hreflang="..."> 注解 增加 URL 计数(Google 已确认:计数器只在 <loc> 上跳,不在 alternate 上)。但它们确实会占 50 MB 大小的份额。

来源:sitemaps.org 协议Google:Build and submit a sitemapGoogle:Manage sitemaps with index files

你属于哪一类

症状大概率原因跳到
解析数量卡在 50,000超过 URL 上限按数量切
文件不到 5 万 URL 却报 Couldn't fetch未压缩超 50 MB按大小切
文件很大但 <loc> 数看着不高hreflang/图片把字节撑大了按大小切,不是按数量
提交了 index 但只有一个子文件被处理index 只列了一个文件或列了自己修 index
切出来某个文件还是超上限按字母切,不是按数量按数量重切
Google 不理你的新文件robots.txt 还写着旧文件修 robots.txt

常见原因

1. 单 sitemap 生成器,没分块

构建脚本不管多少都写进一个 sitemap.xml<loc> 数过 5 万之前都没事。

怎么判断grep -c '<loc>' public/sitemap.xml。到了或超过 50,000,就是超过 URL 上限了。(别用 wc -l——压缩过的 XML 可能把所有 URL 塞在一行里。)

2. URL 不到 5 万但未压缩超过 50 MB

每条 URL 可能带长 <loc><lastmod>、好几个 <xhtml:link> hreflang 标签和 <image:image> 块。注解一多,URL 还没到 5 万就能撞 50 MB。

怎么判断ls -lh public/sitemap.xml。未压缩过 50 MB,不管多少 URL 都得切。

3. Hreflang 撑大的是文件大小,不是 URL 数

en/zh 双语站每个 <url> 加 2-3 个 <xhtml:link>。这些 alternate 算进 5 万 URL 上限——只有 <loc> 算——但它们占字节,能把你顶过 50 MB。注意另一种情况:如果你把 enzh 写成两个独立 <url> 块(两个 <loc>),那每个都算,于是 3 万页的双语站其实有约 6 万个 <loc>,已经超线。

怎么判断:对比 grep -c '<loc>' public/sitemap.xml(真实 URL 数)和 grep -c '<url>' public/sitemap.xml<loc> 接近 5 万就是数量问题;<loc> 没事但文件很大就是大小问题。

4. Sitemap index 指向自己或者漏了

你做了 index 但只列了一个子文件(还是原来那个 7.3 万的),或者不小心把自己也列进去了。

怎么判断cat public/sitemap.xml。应该是 <sitemapindex> 里有多个 <sitemap><loc> 子项指向不同子文件,每个都在上限内。任何子项都不该指回 index 本身。

5. 按字母而不是按数量切

简单粗暴:按 slug 首字母切 sitemap-a.xmlsitemap-b.xml。如果 30 万 URL 里有 8 万都以 “p” 开头,那个文件还是爆。

怎么判断for f in public/sitemap-*.xml; do echo "$f $(grep -c '<loc>' "$f")"; done。任何文件过 50,000,说明切分依据错了——按数量切,别按字母。

6. 压缩后小于 50 MB 但解压后超

Google 看未压缩大小。8 MB 的 sitemap.xml.gz 解压到 80 MB 也会失败。

怎么判断gzip -l public/sitemap.xml.gz 会打印压缩前后字节数。未压缩那一列必须低于 52,428,800。

7. Sitemap 文件跟 robots.txt 不一致

你切成了 sitemap-1.xmlsitemap-2.xml,但 robots.txt 还写着 Sitemap: https://example.com/sitemap.xml 指向旧 urlset,或者什么都不指。

怎么判断curl -s https://yoursite.com/robots.txt | grep -i sitemap。应该列 sitemap-index 的 URL。

最短修复路径

第 1 步:定切分大小和方案

保守目标:每文件 25,000 个 <loc> URL 25 MB——硬上限的一半,这样两次部署之间内容暴涨或某批 lastmod 变大也不会顶线。按内容类型分组,子文件出问题时好定位:

  • sitemap-articles-1.xmlsitemap-articles-N.xml
  • sitemap-categories.xml
  • sitemap-tags.xml
  • sitemap-pages.xml(静态页)

第 2 步:分块生成子 sitemap

// scripts/generate-sitemaps.mjs
import fs from 'node:fs';

const CHUNK = 25000;
const articles = JSON.parse(fs.readFileSync('articles.json', 'utf8'));
const total = articles.length;
const numFiles = Math.ceil(total / CHUNK);

for (let i = 0; i < numFiles; i++) {
  const chunk = articles.slice(i * CHUNK, (i + 1) * CHUNK);
  const urls = chunk.map(a => `<url><loc>https://example.com/articles/${a.slug}/</loc><lastmod>${a.modifiedAt}</lastmod></url>`);
  fs.writeFileSync(
    `public/sitemap-articles-${i + 1}.xml`,
    `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls.join('')}</urlset>`
  );
}

第 3 步:生成 sitemap index

const indexEntries = [];
for (let i = 1; i <= numFiles; i++) {
  indexEntries.push(`<sitemap><loc>https://example.com/sitemap-articles-${i}.xml</loc><lastmod>${new Date().toISOString()}</lastmod></sitemap>`);
}
indexEntries.push(`<sitemap><loc>https://example.com/sitemap-categories.xml</loc></sitemap>`);

fs.writeFileSync(
  'public/sitemap.xml',
  `<?xml version="1.0" encoding="UTF-8"?>\n<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${indexEntries.join('')}</sitemapindex>`
);

顶层文件还叫 sitemap.xml,原有 robots.txt 引用不用改——只是它现在是 <sitemapindex> 不是 <urlset>。index 本身没有自己的 URL;千万别加一个指回 sitemap.xml<sitemap> 项。

第 4 步:更新 robots.txt

User-agent: *
Allow: /

Sitemap: https://example.com/sitemap.xml

index 就在同一个 URL,所以这行可以原样不动——只要确认它指向的是 index,而不是残留的旧 urlset。

第 5 步:每个文件都验证

for f in public/sitemap*.xml; do
  echo -n "$f: locs="
  grep -c '<loc>' "$f"
  xmllint --noout "$f" && echo "  valid XML"
done

每个子文件 <loc><= 50,000,未压缩低于 50 MB。index 里是 <sitemap> 项,不是 <url> 项。xmllint(来自 libxml2)能查出未转义的 &、坏标签、编码问题——这些正是让 Google 报 Couldn't fetch 的原因。

第 6 步:在 Search Console 重新提交

Search Console → Indexing → Sitemaps。删掉原来那个单 sitemap 项。在 Add a new sitemap 里填域名后面的路径(比如 sitemap.xml)然后 Submit。只提交 index 就够了——Google 会自动发现并处理子文件。你也可以在 Sitemaps 报告 里手动触发抓取。

第 7 步:确认修好了

  • Sitemaps 报告里,index 那行显示 Status: SuccessDiscovered URLs 是所有子文件的合计(重复只算一次)。几天内看它涨过 5 万。
  • 点进每个子 sitemap;都不该是 Couldn't fetch。如果有,直接在浏览器打开那个文件 URL,查 HTTP status 和 XML。
  • 在 index(或某个子文件)上点 See page indexing,把 Page Indexing 报告过滤成这些 URL,看已索引数往上走。

被发现不等于被索引——索不索引仍由 Google 决定——但每个合法的 <loc> 现在至少能被 发现,这正是之前被截断的文件做不到的。

哪些情况可能不是你操作错了

URL 不到 5 万的站,切分帮不上忙。这个上限只在规模上去之后才咬人;5 千 URL 的站别去分片。

容易误判的情况

误判为 crawl-budget 问题。Crawl budget 确实存在,但主要影响百万级 URL 的大站。5 万每 sitemap 的硬上限更明确、更简单,先排除它。

预防建议

  • 生成 sitemap 时硬性分块(比如每文件 2.5 万个 <loc>)。
  • CI 里部署前校验 XML;任何文件超 40 MB 或 4 万 URL 就让构建失败。
  • robots.txt 永远指向一个 canonical 的 sitemap-index URL。
  • 构建输出里记录每个 sitemap 的大小和 <loc> 数,趋势在撞线之前就能看到。
  • 传输用 gzip,但断言未压缩大小始终低于 52,428,800 字节。

FAQ

  • hreflang 的 alternate URL 算进 5 万上限吗? 不算。只有 <loc> 算。<url> 块里的 <xhtml:link rel="alternate"> 注解不增加计数,但会占 50 MB 大小份额。
  • 能不用 index、直接分别提交多个 sitemap 吗? 可以,但 index 是标准,每个资源能扩到 500 个 sitemap,比手动提交一堆文件好维护太多。
  • 50 MB 上限是按压缩前还是压缩后算? 压缩前——Google 看未压缩大小(52,428,800 字节)。gzip 只帮传输提速。
  • Bing 也是 5 万上限吗? 是的。5 万 / 50 MB 是 sitemaps.org 协议官方上限,主流搜索引擎都遵守。
  • 一个 index 能列多少个子 sitemap? 最多 5 万,且 index 自己也得低于 50 MB。多数站根本到不了这量级。

相关阅读

标签: #SEO #排查 #收录 #Search Console #Sitemap #xml