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 被發現的過程也就少一些無谓的等待。