先理解一件事:搜索蜘蛛看到的是字符串,不是页面
搜索蜘蛛在决定要不要抓一个 URL 之前,处理的对象是一串字符,而不是你脑子里的那个页面。所以同一个目标页,只要在入口页里被写成两种不同的字符串,就存在被当作两个 URL 记录、两次抓取的可能。
它确实会先做一轮基础规范化,把明显等价的写法合并掉。但这轮规范化有边界,边界之外的差异会被原样保留。入口页的链接写法不统一,浪费的正是这部分:抓取次数花掉了,覆盖的却还是同一个页面。
搜索蜘蛛通常会自动处理哪些差异
下面这些差异,一般在抓取前就会被归一,不会各自成为独立 URL:
- 协议与主机名的大小写,例如 HTTP://Example.com 会被当作 http://example.com;
- 默认端口,:80 和 :443 通常会被去掉;
- URL 里的 #片段,片段不会发送给服务器,一般不参与区分;
- 相对路径,会被解析成完整的绝对地址;
- 部分多余的转义字符。
注意,这一层只是格式上的合并,不涉及内容判断。它不会去分析两个地址返回的 HTML 是否一样。
哪些差异通常会变成两个 URL
下面这些差异,搜索蜘蛛一般不会替你合并,会当成不同地址分别进入待抓取队列:
- 路径大小写:/Page 与 /page。多数 Linux 服务器区分大小写,确实可能是两个资源,搜索蜘蛛没有理由假设它们相同;
- 结尾斜杠:/a 与 /a/。服务器可能返回 200、也可能返回 301,搜索蜘蛛只能按响应判断;
- 跟踪参数:?utm_source=x 与 ?utm_source=y,值不同就是不同字符串;
- 参数顺序:?a=1&b=2 与 ?b=2&a=1,字符串不同;
- 默认文档:/ 与 /index.html;
- 协议与 www:http 与 https、带 www 与不带 www,只要服务器没有强制跳转,就是三四个地址。
对蜘蛛池入口页意味着什么
入口页的作用是让目标 URL 被看见。如果同一条目标 URL 在入口页里以参数、大小写、斜杠混着写,日志上会显得抓取量不小,但去重之后可能只覆盖一个页面。抓取配额被切碎,真正需要被发现的其它 URL 反而排在后面。
更麻烦的是统计失真。按原始 URL 统计,你会以为覆盖了 200 个地址;按规范化后的地址归并,可能只有 60 个。
实际操作上可以这样收敛
- 给每条目标 URL 定一个规范形态,统一大小写、统一是否带结尾斜杠、统一是否带 www 和协议,之后所有入口页只写这一种。
- 服务器端做 301 收敛。把 /a/、/A、/index.html 这类变体统一跳到规范地址,这是最有效的一步,因为搜索蜘蛛最终会跟随到同一个落点。
- 页面里加 canonical,指向规范地址,作为服务器跳转的补充。
- 入口页尽量不带跟踪参数。统计需求可以通过日志或服务器端埋点解决,不必写进链接。
- sitemap、内链、外链写法保持一致,只要有一处不一致,就多一条待抓取记录。
规范化是站点自己该做的事。搜索蜘蛛只负责按字符串抓取和按响应判断,它不会因为"你觉得这是同一个页面"就替你合并。
怎么验证有没有做到位
几个成本不高的检查方式:
- 取一段日志,按规范化后的路径分组,看同一路径出现了几种原始写法;
- 手动访问变体地址,看返回的是 200 还是 301,跳向哪里;
- 在搜索控制台里看已收录地址,是否出现同页多地址的情况;
- 改动后隔一段时间再抽样,确认变体写法在减少。
小结
入口页里 URL 写法不统一,通常不会让页面打不开,但会让 URL 发现的效果打折。先把规范形态定下来,再用 301、canonical 和统一的内链写法把变体收敛掉,日志看起来会更清楚,抓取也更集中。
另外提醒一句:不要反过来刻意制造变体,指望"地址多就覆盖广"。变体带来的是重复抓取,不是更多的有效覆盖。