URL 里出现中文、空格、加号、&、# 这些字符并不少见,站内搜索页、商品筛选页、带中文标题的文章地址都会遇到。麻烦的地方在于:同一条地址,浏览器、CMS 后台、编辑器、外链来源和统计工具可能各自用不同的编码方式写出来,服务器如果都返回 200,蜘蛛就会把它们当成若干条不同的 URL 分别抓取和收录。
同一条地址常见的几种写法差异
- 中文:显示成“中文”还是被编码成 %E4%B8%AD%E6%96%87;同一个字在不同字符集下的百分号串完全不同。
- 空格:写成 %20 还是 +,两者在查询串里常被当成一个意思,但在路径部分含义不一样。
- 百分号编码的大小写:%2f 与 %2F、%3a 与 %3A,多数服务器不区分,少数环境会区分。
- 路径尾部:带不带斜杠、带不带默认文件名,例如 /list 与 /list/、/list/index.html。
- 参数:顺序不同(?a=1&b=2 与 ?b=2&a=1)、空参数保留(?a=&b=2)、各种追踪参数。
- 锚点:# 后面的内容不会发给服务器,但有些转载或跳转会把带锚点的整串当成独立地址。
- 复制粘贴造成的二次编码,比如中文字符被编成 %25E4... 这种多套一层的形式。
编码分裂会带来哪些实际问题
抓取被摊薄是最常见的。同一个页面有好几种写法,蜘蛛每次抓到的是不同地址,重抓频率被分散,新内容的发现速度也跟着变慢。其次是信号分散:如果每种写法各自有一套 canonical、内链和分享数据,搜索引擎很难判断哪个才是主副本,收录数看着在涨,但有效页面并没有增加。日志分析同样会被带偏,你以为蜘蛛抓了 100 个页面,实际可能只有 60 个是真正不同的内容。
先确认有没有真的分裂
- 站内走一遍:从首页、列表页、站内搜索、标签页分别点到同一个内容,对比地址栏里的 URL 是否一致。
- 看日志:把同一资源(比如同一个商品 ID 或文章 ID)对应的请求 URL 归到一起,数一数有几种写法。
- 看索引:用站点查询或相关工具查看同一内容是否出现了多个地址,结果只当线索,不要当成精确的收录数量。
- 检查出口:sitemap、canonical、RSS、内链、分享按钮里写的是哪一种写法,彼此是否统一。
收口的顺序
- 先定一条规范写法。中文 slug 尽量用拼音或英文短语,减少直接暴露编码;确实需要保留中文的,就固定使用一种编码,通常是 UTF-8。
- 在服务器层收口,把其他写法 301 到规范写法。这比只写 canonical 更干脆。对大小写敏感的服务器要单独确认,别想当然。
- 内链、sitemap、canonical、结构化数据里的地址全部对齐规范写法,不要留下任何一处老写法。
- 参数做取舍:筛选、排序、追踪参数尽量不进可收录的地址;必须保留的,固定参数顺序,避免同一组条件产生多种排列。
- 改完后观察一段时间,看旧写法的请求是否逐渐减少,索引里的重复地址是否回落。
canonical 是建议,301 是硬跳转。两者都做会更稳,但不要以为只写一条 canonical 就算收口完成。
两个容易忽略的细节
一个是外部写法。别人复制地址时可能带上追踪参数,或者把中文二次编码,这类写法你控制不了,但可以确保服务器把它们 301 到规范地址,而不是各自返回 200 的重复内容。另一个是锚点与分页的误用:把 #section 当成独立 URL 提交给搜索引擎,或者把同一页面的多个分页当成独立内容,都会加重重复。
收口不需要一次做完。先把站点自己能控制的出口统一,再处理外部写法,最后用日志验证。判断标准很简单:同一个内容,不管从哪里点进来,最后落在地址栏里的字符串应该是一样的。