Sitemap 说起来简单:一份 URL 清单,放在站点根目录,提交给搜索引擎。但当站点有几万、几十万条 URL 时,单文件会被规则卡住,蜘蛛也不一定读得完。这时候要处理的不是「写不写 Sitemap」,而是「怎么拆、怎么串、怎么维护」。
单文件的上限在哪里
通用的 Sitemap 协议里,一个文件最多包含 50,000 条 URL,未压缩体积不超过 50MB。超过这个量,就要拆成多个分片文件,再用一个索引文件(sitemapindex)把它们串起来。索引文件本身也受同样两条限制,所以理论上可以分层,但实际很少需要嵌套到第三层——嵌套越多,蜘蛛要走的路径越长,中途出错的机会也越多。
索引文件里只放什么
- 每个 loc 指向一个分片 Sitemap 的完整地址,必须是绝对 URL
- 可选的 lastmod 表示该分片最近一次变动时间
- 不放具体页面 URL,也不放 priority、changefreq 这类对分片本身没有意义的字段
常见的错误是把页面 URL 和内层 Sitemap 混写在同一个索引文件里,或者让两个索引文件互相指向。这类结构蜘蛛往往只能读到其中一部分,剩下的部分就一直停在「未被发现」的状态。
分片按什么维度切
拆分的维度没有标准答案,但有几个比较实用的思路:
- 按内容类型:文章、商品、分类、标签各成一份,便于分别观察抓取情况
- 按更新时间:高频更新的内容单独一份,低频内容单独一份,避免每次都要重读全量
- 按目录或语言:多语言站点按语言拆,站点结构清晰时按一级目录拆
- 按体量均分:没有明显分类时,直接按数量切成每份两万到三万条
切完之后,每份分片最好控制在几百 KB 到一两 MB 之间。文件太大时,蜘蛛读取和解析的成本都会上升;太小又会分出几十上百个文件,索引文件本身变长,得不偿失。
lastmod 怎么填才算诚实
lastmod 是蜘蛛判断「这份清单值不值得重新读」的重要参考。如果每次生成时都刷新成当前时间,即使内容没变,蜘蛛迟早会不再信任这个字段;反过来,一份长期不更新的清单里塞进新页面,新 URL 被发现的时间也会被拖后。比较稳妥的做法是:只有当分片内确实有页面新增或内容变动时,才更新对应的 lastmod,格式统一用带时区的 ISO 8601。
它和内链、抓取路径的分工
Sitemap 解决的只是 URL 发现这一环,它告诉蜘蛛「这些地址存在」,但不太决定「先抓谁」。蜘蛛真正在站内行走时,依据的还是链接——导航、列表、正文、相关推荐里的 a 标签。所以常见的情况是:某些页面在 Sitemap 里躺了很久,但因为站内没有任何链接指向它,被抓取的次数一直很低。把重要 URL 放进 Sitemap 之外,还要给它在站内留一条真实可点的入口,两者配合才有意义。
服务器这一层别掉链子
Sitemap 文件本身也是普通资源,蜘蛛访问时同样受服务器状态影响:
- 要稳定返回 200,避免用 302 跳转到另一个地址
- 出错时不要返回一个 HTML 错误页冒充 XML,解析会直接失败
- 开启 gzip 压缩,压缩后提交体积上限才算数
- 不要用 robots.txt 挡住 Sitemap 路径,否则蜘蛛读不到清单
如果服务器在大流量时段响应变慢,Sitemap 的抓取频率也可能跟着下降,这与站内页面的情况是一致的。
几个容易踩的坑
- URL 没有做转义,带 & 或中文的参数直接写进 XML,导致解析错误
- 清单里混入大量重定向地址、404 页面或已下线的 URL
- 大小写、结尾斜杠与线上实际地址不一致,被当成另一个 URL
- 分片文件更新了,索引文件的 lastmod 却没跟着动
- 同一批 URL 同时出现在多份分片里,重复且难排查
把 Sitemap 当成一份需要长期维护的索引,而不是一次性提交的任务。清单保持干净、分片边界清楚、lastmod 诚实,蜘蛛读得顺,新 URL 被发现的过程也就少一些无谓的等待。