先弄清楚:同一份内容为什么会有多个地址
蜘蛛抓取时看到的不是「页面」,而是一个个 URL。同一份内容落在多个 URL 上,抓取请求就被分摊到这些地址里,日志里看起来像每个地址都抓了一点,但哪个都没抓透。常见来源有:
- 协议与主机名不统一:http 与 https、带 www 与不带 www 同时可访问。
- 大小写与尾斜杠:/Page 与 /page、/list 与 /list/ 各自返回 200。
- 跟踪参数:渠道来源参数、会话参数、广告点击 ID 被带进了内链。
- 排序与视图参数:?sort=、?view=、?page=1 与不带参数时返回的内容一致。
- 功能页复制:打印页、导出页、独立移动版地址。
- 多域名指向同一套站:备用域名、测试域名没有做访问限制。
这些地址如果都能返回 200,蜘蛛就会各自排队;如果其中一部分被 robots.txt 屏蔽,问题会变成「抓了但抓不到内容」,排查起来更绕。
蜘蛛在多个地址之间怎么挑
没有一个自动去重的开关。蜘蛛看到多个候选地址时,会综合几个信号来挑选主地址,从强到弱大致是:
- 301 跳转:服务器直接指向唯一地址,信号最明确。
- rel=canonical:页面自己声明主地址,属于提示性质。
- Sitemap 里的写法:站点地图给出的地址通常被当成站方认可的主入口。
- 内链与导航:站内链接大多数指向哪个写法,蜘蛛更倾向沿用哪个。
- 外部引用:外站链接指向的版本会被当作参考。
麻烦在于这些信号经常互相矛盾:canonical 指向 A、内链大量指向 B、Sitemap 里写的是 C。冲突时蜘蛛只能自己选,结果往往不是你想要的那一个。
用日志核对三件事
- 统计每个重复地址的抓取次数与返回状态码,看是否出现两个地址被平均抓取的分流现象。
- 看抓取入口从哪来:是 Sitemap、内链还是外链,找到把旧写法扩散出去的源头。
- 抽几个地址对比返回内容,确认还是同一份内容,还是已经出现了分叉。
收敛顺序:把改动放在信号最强的地方
先做服务器层,再做页面层,最后清内链。顺序反了,改动容易被旧信号抵消。
- 统一协议与主机名:确定一个主地址,其余用 301 永久跳转,尽量不要用 302 或 JS 跳转。
- 规范大小写与尾斜杠:让服务器只认一个写法,其余一律 301,不要两种写法都返回 200。
- 页面内 canonical 指向主地址,使用绝对地址,不要指向自身以外的重复页。
- 过滤参数:能被内链生成的参数尽量去掉;必须带参数的页面,让它 canonical 到无参数版本,或做其他处理,二选一,别同时做。
- 清理站内链接:导航、面包屑、列表页模板里的地址写法统一,尤其是模板批量生成的内链。
- Sitemap 只留主地址,把重复地址从地图里剔除。
canonical 是提示而非指令,301 才是硬信号。能用跳转解决的,不要只写一行 canonical 就收工。
几个容易踩的坑
- canonical 指向一个被 robots.txt 屏蔽的地址,等于把信号送进了黑洞。
- 分页的第 1 页 canonical 指向无参数版本,第 2 页及以后也全部指向第 1 页,深层内容会被从抓取路径里切断。
- 用 canonical 把别家的内容指到自己站,短期看着舒服,实际是典型的错误做法。
- 测试域名没有做访问限制,蜘蛛抓到了两份几乎一样的站点。
改完之后看什么
改动上线后,别急着盯收录数量,先看日志里的抓取分布:重复地址的抓取次数应当逐步下降,主地址的抓取次数上升;Sitemap 中上报的地址与实际被抓取的地址应当逐渐一致。这个收敛过程通常要几周到一两个月,期间要保证内链和 Sitemap 不再生成旧写法,否则又会被拉回去。