站点小的时候,一个 sitemap.xml 就能装下全部 URL。等到文章上千、栏目几十个,单文件要么体积超标,要么每次生成都拖慢服务器。这时候就要用 sitemap 索引文件(sitemap index)把地图拆成多份。拆得合理,蜘蛛读取顺畅;拆得随意,反而制造新的抓取障碍。
什么时候该拆分
常见的两个硬限制:单份 sitemap 里的 URL 数量不超过 5 万条,未压缩体积不超过 50MB。接近任意一条,就该考虑分片。还有一种更隐蔽的情况:站点 URL 只有几千条,但每次请求 sitemap 都要实时查库拼装,接口耗时两秒以上——问题不在数量,而在生成方式。
三种常见的分片切法
- 按栏目或目录切:文章、商品、问答各自一份,结构清晰,新增栏目时改动小。
- 按更新时间切:把近期更新的 URL 单独放一份,蜘蛛每次优先读这份,老内容放历史分片,读取频率降低。
- 按内容类型切:页面、图片、视频、新闻分别成文件,各自遵循对应的格式要求,避免混在一起导致解析报错。
三种可以组合使用。切分的目的不是好看,而是让蜘蛛用更少的请求拿到更准确的信息。
索引文件的写法与入口
索引文件本身只包含各个分片的地址和最后修改时间,不列具体 URL。它同样受 50MB 限制,但一般远达不到。关键是入口要让蜘蛛找得到:在 robots.txt 里用 Sitemap 指令声明索引文件地址,同时保证分片 URL 返回 200,且写的是完整的绝对地址。
多级索引(索引指向索引)在规范里是被允许的,但层级越深,中间环节出错的机会越多。两层通常够用。
lastmod 别当摆设
lastmod 写“今天”最省事,也是最容易被忽略的做法。如果每份分片的最后修改时间每天都在变,蜘蛛会认为整站天天在更新,久而久之对这个字段失去信任。建议让 lastmod 反映内容真实改动的时间,批量改模板导致的时间戳变动,可以在生成逻辑里排除。
动态生成的两点注意
- 加缓存:把生成的 sitemap 落盘或放 CDN,设置合理的过期时间,别让每次蜘蛛访问都打数据库。
- 超时兜底:接口慢于几秒时返回上一次的缓存版本,也好过返回 500 或空文件。
分片之后容易踩的坑
- 索引文件里指向了已删除或改名的分片,返回 404,却没被及时发现。
- 分片返回 200,但内容是空的或只有 XML 头,蜘蛛读到的是“这一批没有 URL”。
- 分片内混入了 301、404、noindex 的地址,等于把无效路径反复送出去。
- 用 gzip 压缩后没设置正确的 Content-Type,解析可能直接失败。
- 分片数量太多太碎,几千个 URL 拆成几十个文件,反而增加读取成本。
Sitemap 只是补充,不是替代
Sitemap 解决的是“告诉你这里有哪些 URL”,它不解决“这个 URL 值不值得抓”。页面的内链位置、被引用的次数、内容本身的质量,才是决定抓取优先级的部分。
把 URL 写进 sitemap,不意味着它会被抓取,更不意味着会被收录。它的价值在于降低蜘蛛发现不了的概率,尤其是层级深、内链少的页面。如果一篇文章在任何列表页都找不到入口,只存在于 sitemap 里,即使被抓到,后续的重新抓取也会缺少触发路径。
一个简单的自查顺序
- 打开索引文件,逐个点开分片,确认都返回 200 且内容非空。
- 抽查分片里的 URL,确认不是 404、301 或已设 noindex。
- 核对最后一层的分片数量与 URL 总量是否对得上。
- 看服务器日志里 sitemap 相关请求的响应时间与状态码。
- 确认 robots.txt 里的 Sitemap 指令没有被注释掉或写错域名。
这几步花不了太多时间,但能挡掉大部分“sitemap 提交了却没动静”的情况。真正影响抓取效率的,往往不是地图本身,而是地图背后那些生成不稳、地址失效、更新失真的细节。