canonical 到底在解决什么问题
同一段正文,常常因为 URL 写法不同而变成好几个地址:带 www 和不带 www、http 和 https、结尾有没有斜杠、参数顺序不同、大小写不同、移动版单独挂在另一个域名下……对用户来说这是一个页面,对爬虫来说这是多个 URL。canonical 的作用就是明确告诉蜘蛛:这一组地址里,哪一个才是应该保留的主版本。
它不阻止抓取,也不保证替换索引,只是尽量把重复信号收敛到主版本上,减少抓取预算被浪费在变体地址上。
最容易漏掉的重复来源
- 协议与域名变体:http 与 https、www 与裸域同时可访问。
- 末尾斜杠与大小写:/about 与 /About/ 返回同一份内容。
- 跟踪参数:utm_ 系列、from=、ref= 等只是渠道标识,却生成了新 URL。
- 站内搜索结果页与筛选页:颜色、价格区间、排序方式组合出的地址。
- 打印页、AMP 页、单独拆出来的移动版。
- 分页列表:第一页与不带页码的地址其实是两份正文。
自查时按这个顺序做
- 先用站内搜索或抓取工具,找出标题、正文高度相似但 URL 不同的一组组地址。
- 每组挑一个“最该保留”的地址:可读性好、有内链指向、有稳定访问。
- 在其余变体页面的 head 里加 rel="canonical",写绝对地址,并确保目标能返回 200。
- 主版本自己也要写一条指向自身的 canonical,避免解析时找不到明确信号。
- 同组内的内链统一指向主版本,不要一边声明 canonical,一边大量链向变体。
提醒:canonical 是建议而不是命令。当页面内容差异过大、指向目标明显不相关,或者目标页返回 404、被 robots 拦住、被 noindex,蜘蛛很可能直接忽略这条声明。
常见的写错方式
- canonical 指向重定向链中间或末端的 404 地址。
- 同一个页面出现多条互相矛盾的 canonical。
- 用 JS 动态插入 canonical,首屏 HTML 里根本没有这条标签。
- canonical 与 hreflang 打架:语言版本之间应互相指向并各自自指,不要全部 canonical 到某一个语言版。
- 用 canonical 把内容差异很大的页面强行合并,试图“借权重”。
- 分页场景下把第 N 页 canonical 回第一页,却没给用户和蜘蛛留下继续翻页的路径。
上线后怎么验证
改完不要只看一眼页面源码就收工,更实用的做法是:
- 用抓取工具批量抓取目标 URL 组,检查状态码、canonical 字段和页面标题是否一致。
- 看日志里这些地址的抓取频次是否逐步向主版本集中,变体地址是否慢慢减少。
- 观察索引中保留的版本,若变体仍被收录,回头检查内链、Sitemap 或站内搜索是否还在产出变体地址。
- 把 canonical 规则写进模板,而不是靠人工逐页补,避免新页面又漏掉。
和 robots、noindex 的分工
这三者经常被混用:robots.txt 是“不要来抓”,noindex 是“可以抓但不要收”,canonical 是“可以抓可以收,但请以这一份为准”。用错会出现“想合并却把页面挡在门外”,或者“想屏蔽却被持续抓取、白耗预算”。先想清楚目的,再决定用哪一个。
最后补一句:canonical 只能减少内部重复,解决不了内容本身的问题。如果变体页面确实有独立价值,更合理的做法是把它做成有独立标题、独立结构的页面,而不是硬合并到别处。