文章分析了网站因重复内容导致收录不稳定的问题,强调了使用Canonical标签和301重定向进行URL规范化的重要性。文章指出使用301和rel=canonical的不同场景,并详细解释了在使用过程中可能遇到的四个常见问题,包括Canonical标签误用相对路径、文章列表分页错误指向首页、HTTP到HTTPS迁移后的信号死锁等,为解决这些问题提供了详细的方法和注意事项。
前段时间翻看站长平台的抓取诊断报告,我发现了一个挺头疼的问题:明明全站只有两百多篇文章,爬虫抓取记录里却堆了快一千个不同的 URL。
顺着日志一查才看明白,很多页面都被抓成了好几个孪生版本:有带尾部斜杠的 /nginx-cache/ 和不带斜杠的 /nginx-cache,有带微信统计参数的 ?from=timeline,还有早年遗留的 http:// 和 https:// 混杂。搜索引擎把这些都当成了独立页面去爬,直接耗光了服务器每天有限的抓取配额,更把页面权重拆分得稀烂,原本排在前面的几篇技术教程排名直线下滑。
这是典型的 URL 规范化(URL Canonicalization)问题。处理这类问题,大家第一反应通常是加 Canonical 标签或者配 301 重定向。但这两样东西配合起来用的时候,如果稍微大意一点,搜索引擎可能不认账,甚至把整站索引搞乱。我把这次排查和调整中踩到的四个细节记录在这里。
什么时候用 301,什么时候用 rel=canonical
很多刚接触 SEO 的朋友容易把 301 和 Canonical 当成二选一的互换方案,实际上它们在搜索引擎爬虫眼里的分工完全不同。
301 是强制重定向。当浏览器或者爬虫请求 URL A 时,服务器直接返回 301 状态码,告诉客户端“这个页面已经永久搬迁到 URL B,以后请直接访问 B”。用户在浏览器地址栏里会肉眼看到地址跳转。这种机制适合那些物理上必须合并的场景,比如:
http://强跳https://- 不带 www 的主域名强跳带 www(或者反过来)
- 路径末尾强制统一带斜杠或不带斜杠
rel=canonical 则是页面头部的标准网址声明。用户访问 URL A 时,页面正常显示,HTTP 状态码也是 200,但在 HTML 的 <head> 里有一行声明:
<link rel="canonical" href="https://example.com/canonical-url">
这行代码告诉爬虫:“虽然你现在抓取的是带跟踪参数或不同分类路径的地址,但这篇内容的原始主版本是 href 里的那个,请把排名权重全部算给主版本,索引库里也只保留主版本。”
简单来说:能且应该强制跳转的,一律走 301;需要给用户正常展示不同参数或聚合视图但内容雷同的,用 Canonical 规范化。
坑一:Canonical 标签误用相对路径
这是我见过的最高频错误,也是我自己一开始偷懒犯的错。
在 HTML 模板里写链接时,大家习惯了写相对路径:
<link rel="canonical" href="/article/128">
按 HTML5 语法规范,相对路径在浏览器解析时会自动拼装基准路径。但各大搜索引擎的爬虫协议对 canonical 有明确规定:必须提供完整的绝对 URL,包含协议(http/https)和主机名。
如果写了相对路径,部分海外爬虫可能勉强解析,但国内引擎经常会直接将其判定为无效标签,甚至在面对带子目录、反向代理或泛域名的站点时,把基准域名拼错成奇怪的地址。
正确的写法必须在模板引擎里拿到站点根域名,拼接成绝对路径:
<link rel="canonical" href="https://www.llbbs.cn/article/128.html" />
如果你用的是常见博客系统或静态生成器,务必检查生成出来的 HTML 源码,确认每一篇文章的 canonical 属性都以 https:// 开头。
坑二:文章列表分页把 Canonical 全指给首页
这个坑破坏力极大。前些年一个朋友的站点更新博客,整站收录从上千暴跌到几十,查到最后就是这个问题造成的。
当时他在做列表页模板优化,心想“/page/2、/page/3 都是文章列表,核心页面就是首页嘛”,于是脑子一热,把所有列表分页的 canonical 统一写成了网站根目录:
<!-- 在 /page/2 的 head 里错误地声明 -->
<link rel="canonical" href="https://www.llbbs.cn/" />
结果爬虫抓到第二页时,看到了这行标签,乖乖听话把第二页当成了首页的重复内容,不再保留第二页的索引,也直接忽略了第二页上挂着的十多篇内页文章链接。一周之后,老文章纷纷掉出索引库。
列表分页绝不是首页的重复版本,每一页包含不同的文章摘要和内部链接。分页的正确处理规则只有两条:
- 分页页面如果保留独立内容,Canonical 必须指向自己本身,即
/page/2的 canonical 就是https://www.llbbs.cn/page/2。 - 只有当你有“查看全部”(View All)聚合单页且性能扛得住时,才可以将各个分页的 canonical 统一指向该聚合页。通常情况下,让每个分页指向自身是稳妥的做法。
坑三:HTTP 到 HTTPS 迁移后产生的信号死锁
很多站点在给全站加 SSL 证书升级 HTTPS 时,容易在服务端和前端模板之间产生信号互斥。
当时我的 Nginx 配置里已经加上了强制跳转:
server {
listen 80;
server_name www.llbbs.cn;
return 301 https://$host$request_uri;
}
这段配置运行正常,所有访问 80 端口的请求都会被重定向到 443 端口。
但我忘记了博客模板里以前写死了一个全局变量 $site_url = 'http://www.llbbs.cn'。导致输出的 HTML 头部变成了这样:
<link rel="canonical" href="http://www.llbbs.cn/article/105.html" />
这就产生了一个恶性循环:
爬虫访问 HTTP 地址,服务器 301 跳转到 HTTPS;爬虫到了 HTTPS 页面,页面头部的 Canonical 又信誓旦旦地声明“真正的规范地址是 HTTP”。两个信号完全相反,直接把搜索引擎给整不会了。Google Search Console 很快就会报出“用户声明的规范网址与 Google 选择的规范网址不一致”,收录排名应声受挫。
在启用 HTTPS 后,一定要在整站代码和数据库配置中把站点 URL 彻底替换成 https://,确保服务器重定向目标与页面 Canonical 声明完全契合。
坑四:Nginx 规范化斜杠时弄丢了查询参数
为了彻底解决 /nginx-cache 与 /nginx-cache/ 两个 URL 竞争的问题,通常会在 Nginx 里做统一重写。比如统一让没有斜杠的目录请求跳转到带斜杠的版本。
网上很多老旧教程给出的规则长这样:
# 存在缺陷的写法
rewrite ^([^.\?]*[^/])$ $1/ permanent;
这段代码的问题在于,如果用户访问的 URL 带着参数,比如微信分享后的 https://www.llbbs.cn/tools?from=timeline,经过这条 rewrite 规则之后,请求会被重定向到 https://www.llbbs.cn/tools/,后面的 ?from=timeline 参数全部丢失。如果这个参数是用来做业务逻辑、文章分页标记或者推广追踪的,程序直接就出错了。
在 Nginx 中做这类 URL 规范化重定向时,推荐使用内置的 $is_args$args 或者利用精确的 location 匹配来保留参数:
# 规范尾部斜杠并保留原始参数
if (-d $request_filename) {
rewrite ^(.*[^/])$ $1/ permanent;
}
# 或者针对特定静态路径做明确重定向
location = /tools {
return 301 https://$host/tools/$is_args$args;
}
通过保留 $is_args$args,既能把路径标准化为带斜杠的唯一版本,又不会把用户或爬虫带过来的参数无故吞掉。
发布后的验证方法
配完规则和模板后,不要干等着搜索引擎来抓,先在本地终端用 curl 做一遍验证。
先验证 HTTP 状态码与重定向头:
curl -I -sL -A "Baiduspider" https://www.llbbs.cn/tools | grep -E "HTTP|Location"
确认重定向链路干净清晰,一次到位,不存在链式重定向(301 接着 301)。
接着检查目标页面的源码头部:
curl -s -A "Googlebot" https://www.llbbs.cn/article/128.html | grep -i 'rel="canonical"'
看到输出带有规范的 https:// 绝对域名且与当前访问路径完全吻合,才算大功告成。
规范化 URL 看起来是细碎琐碎的基础活,但把爬虫引向唯一的目标地址,才能让站内每一份内容积累到的反向链接和用户点击切实沉淀在文章本身。
文章标题:网站重复内容导致收录不稳定?我用 Canonical 标签配合 301 做 URL 规范化,几个坑说清楚
文章链接:https://llbbs.cn/jishujaocheng/235.html
本站文章均为原创,未经授权请勿用于任何商业用途
评论一下?