如何检查重定向链(301/302)并修复

重定向链指的是这样一种情况:一个 URL 不是一步跳到目的地,而是先经过若干中间 URL:http://example.com/page 先 301 到 https://example.com/page,后者再 301 到 https://www.example.com/page,最终返回 200。每多一跳就多一次 HTTP 往返,而且每一跳都是一条可能出错、也可能给迁移贴错标签的规则。本指南将讲解重定向链为何损害 SEO、如何用免费的重定向链检查器逐跳读取整条链路,以及如何把任何一条链压平成一次重定向。

什么是重定向链?

重定向——具体来说是 301、302、303、307 或 308 响应,而不是随便哪个 3xx——通过 Location 响应头告知客户端“你要的页面现在在这里”。所谓链,就是两条或多条重定向首尾相连:

GET http://example.com/old-page
  301 → https://example.com/old-page
  301 → https://www.example.com/old-page
  301 → https://www.example.com/new-page
  200 ← final page

客户端必须依次请求每一个 URL。与之相对,重定向循环会绕回自身(A → B → A),永远没有终点——浏览器会显示 ERR_TOO_MANY_REDIRECTS。重定向链很少是有意为之:迁移往往层层叠加——在旧的 www 合并之上启用 HTTPS,之后再更换平台——却没有人清理早期的规则。

重定向链为何损害 SEO

延迟会层层叠加。每一跳至少耗费一次 HTTP 往返——用跳数乘以访客的往返时延,代价一目了然。跨主机的一跳还要追加 DNS 解析和一次全新的 TCP/TLS 握手;同主机的跳转则可以复用连接。Google 的网站迁移指南警告说“链接式重定向会增加用户延迟,而且并非所有用户代理和浏览器都支持过长的重定向链”——而页面速度正是排名所用 Core Web Vitals 信号的输入之一。

抓取预算被浪费在不复存在的 URL 上。每一次花在跟踪中间变体上的抓取,都是从真实页面那里抢来的。也不要试图用 robots.txt 解决链的问题:Disallow 一个中间 URL 会让 Googlebot 连重定向本身都看不到,它看到的将是一次拦截而非一次跳转。让 robots.txt 只承担真正的抓取指令。

链很脆弱。中间任何一跳断掉,其上游的一切都会走进死胡同——包括指向原始 URL 的外链。

混杂的状态码传递混杂的信号。Google 的重定向文档写得明明白白:对 301,“索引流水线会把该重定向视为‘重定向目标应为规范网址’的信号”;对 302,它“不会把重定向当作信号使用”,源页面会继续留在搜索结果里。链中任何位置的一个 302 都可能推迟甚至阻止权重合并。Google 还说过,存在已久的 302 最终会被当作永久重定向——只是更慢。跳转本身不损失任何东西:按照 Google 网站迁移指南的说法,“301 及其他永久重定向不会导致 PageRank 流失”。

301、302、307、308:选定一种,贯彻到底

  • 301(Moved Permanently,永久移动)——永久迁移。网站迁移、URL 重写、http 升级 https、www 合并的默认选择。
  • 302(Found,临时重定向)——临时跳转;旧 URL 仍是规范网址。适用于 A/B 测试、短期促销、地理定向。
  • 307 / 308——更严格的临时与永久状态码:必须以相同的请求方法和请求体重放。

问题始于混用:几年前你把 /old-lp 301 到了 /spring-campaign;今年市场部又用 302 把 /spring-campaign 指向一个新页面,理由是“这只是个活动页”。这条 301 → 302 的链把永久性只宣告了一半。一次性定夺:永久——每一跳都是 301;临时——从原始 URL 发出一个 302。

如何逐步检查一条重定向链

免费的重定向链检查器以爬虫的视角跟踪链路:每一跳都是一次全新的 HTTP GET——不带缓存、不带 Cookie、不执行 JavaScript、不做 HSTS 升级——user agent 为 GeoToolsBot/1.0。

第 1 步:收集值得测试的 URL

要数据来源,不要凭空猜测:当前与历史 sitemap、服务器访问日志、Search Console 的“链接”报告(用于找出被外部链接的页面)——这正是 Google 网站迁移指南推荐的信息源——再加上重点页面的 http:// 与无 www 变体,以及外链导出数据。

第 2 步:运行检查

把 URL 粘贴进重定向链检查器,按下 Check redirects(检查重定向)。工具在禁用自动跳转的状态下请求该 URL,读取 Location,解析后继续——最多六跳,每一步都做循环检测。你会看到每一跳的状态徽章、URL 和目标地址,以及最终落地页与内容类型。我们实测的健康参照 http://github.com:一次 301,随后 200。

第 3 步:阅读问题列表

检查器还会标记真正有害的情况:超过三跳的链——对应 Google“理想不超过 3 跳、务必少于 5 跳”的建议;第一跳之后仍是明文 http:// 的跳转,说明 HTTPS 升级被延误;永久与临时状态码混用;跨域跳转——离开你的可注册域(你注册的那一部分:example.com,而非 shop.example.com),Google 会将其视为一次网站迁移,附带专属检查清单(包括“地址更改”工具);以 PDF 等非 HTML 页面收尾;以及以 4xx/5xx 收尾。绕圈的 URL 返回的是循环错误而非一条链。

第 4 步:工程师的抽查路线

curl -sI http://github.com          # first hop only
# HTTP/1.1 301 Moved Permanently
# Location: https://github.com/

curl -sIL http://www.apache.org     # headers for EVERY hop
# HTTP/1.1 301 Moved Permanently
# Location: https://www.apache.org/
# HTTP/2 200

curl -s -o /dev/null -w 'status=%{http_code} redirects=%{num_redirects} final=%{url_effective}n' -L http://github.com
# status=200 redirects=1 final=https://github.com/

实测中有两点提醒:-I 发送的是 HEAD 请求,而部分服务器对 HEAD 另眼相待——github.com 在我们这里挂起过,GET 却一路畅通。此外,最终 403 不一定就是坏了:截至撰写本文时,stackoverflow.com 先给出干净的 301,随后对爬虫返回 403。请先在浏览器里复查那些“失效”的最终页面。

如何把链压平成单次跳转

目标是:任何发生重定向的 URL 都直接指向最终目的地。没有中间人。

  1. 先画清链路。在动手之前,把确切的每一跳和状态码记录下来。
  2. 改写第一跳。在 nginx 中,把 return 301 https://www.example.com/new-page; 放进监听 80 端口的 server 块(或旧主机的 server 块)。在 Apache 中,Redirect 301 /old-page https://www.example.com/new-page 依赖 mod_alias,写在 vhost 或 .htaccess 里;它按整个路径段匹配,所以 /old-page 也会命中 /old-page/sub——要精确匹配就用 RedirectMatch 301 ^/old-page$ https://…/new-page。在 WordPress 中,Redirection 插件把这张映射表管理在数据库里。
  3. 停用或改指中间跳。删除规则之前,先确认没有真实来源指向那里:检查外链导出数据,并 grep 访问日志。仍有外部链接落在中间 URL 上?把它也一并改指。
  4. 修正内链。重定向是为那些你改不了的 URL 准备的——别人的外链。自己的链接直接指向最终 URL;内链往往是重定向链最大的单一来源。
  5. 复查并更新 sitemap。在链检查器里确认只剩状态码正确的一跳。然后重新生成 sitemap,使其只列出最终 URL,并在 Search Console 的“Sitemaps”报告里提交;生成交给免费的XML sitemap 生成器即可。

要合并 http 和 www?一次跳转就够,别写两条各干一半的规则——http://example.com 会被迫先经过 https://example.com 再去 https://www.…,而顺序写反的强制 TLS/强制 www 规则正是经典的循环诱因:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://www.example.com$request_uri;
}

再有一个陷阱:有些规则会悄悄丢弃查询字符串。Apache 的 mod_alias Redirect 会把 GET 参数原样传递,但 RewriteRule 的目标一旦自带 ?,原始查询字符串就会被丢弃,除非加上 [QSA]([QSD] 是刻意丢弃)。像 /?utm_source=newsletter 这样的活动链接一旦被剥掉参数,统计就会失真——请用UTM 构建器生成链接,并确认参数完好送达。

应避免的常见错误

  • 迁移层层叠加。先 http→https,再 www,然后换平台——每一层都把重定向叠在上一层之上。
  • 用 302 处理永久迁移,只因为它是 CMS 的默认设置。
  • 把浏览器当测试依据。浏览器会激进地缓存 301,HSTS 还会在第一次请求之前就把 http 升级成 https——浏览器里显示的跳数可能少于实际。
  • 只修第一跳。中间跳仍在接收旧外链传来的链接权重。
  • 为了“节省抓取预算”在 robots.txt 里屏蔽中间 URL——Googlebot 从此看不到那次重定向。
  • 随手把页面重定向到某个现成页面,而非对等页面——问题没修复,只是链更短。

常见问题

一条重定向链有多少跳算过多?

按照 Google 网站迁移指南:Googlebot 最多会跟随 10 跳,但建议直达目的地,链长“理想不超过 3 跳、务必少于 5 跳”。检查器与之对齐——超过三跳即标记,六跳后停止。

301 重定向会损失 PageRank 吗?

不会——Google 的网站迁移文档明确写道“301 及其他永久重定向不会导致 PageRank 流失”,Google 的 Gary Illyes 也在 2016 年的一条推文里说过同样的话。但重定向链仍会让你付出代价:延迟、抓取预算、脆弱的规则,以及推迟权重合并的临时状态码。

重定向链和重定向循环有什么区别?

链最终会到达一个真实页面:A → B → C → 200。循环则绕回自身——A → B → A——永远没有结果;浏览器会显示 ERR_TOO_MANY_REDIRECTS。修法也不同:循环需要找出并拆除相互冲突的规则,而不是把某一跳改指。

为什么我的浏览器显示的链与检查器不同?

有两个机制。其一是浏览器会缓存重定向,301 缓存得最顽固——规则早已更改,Chrome 仍会长时间沿用缓存的重定向。其二是 HSTS:浏览器一旦见过 Strict-Transport-Security 响应头(或通过预加载列表获知),就会在第一次请求之前把 http 升级为 https,从而藏起那一跳。检查器每次都是全新请求,不带任何 HSTS 列表。

如何修复 WordPress 里的重定向链?

大多数链来自插件重定向、.htaccess/nginx 规则与 HTTPS/www 重写的层层叠加。请盘点每一个来源——Redirection 插件的重定向列表及其日志(Logs)页面、服务器配置、任何 SEO 插件里的重定向——然后逐条改写,让原始 URL 一次 301 直达最终目的地。更新内链,再用检查器复查。

Google 需要多久才能识别修复后的重定向?

重新抓取按 URL 逐个进行,节奏由 Googlebot 决定——中小型网站通常几周,大型网站更久。可以通过 Search Console 的“网址检查”工具请求编入索引并提交更新后的 sitemap 来加快进度。重新处理期间出现波动属正常现象。

旧的 301 规则应该保留多久?

Google 建议重定向至少保留一年——理想更久——以便信号完成传递、外部网站更新链接。删除任何规则之前,先确认已无剩余外链(检查链接导出数据),访问日志里也没有真实流量。

能批量检查重定向链吗?

免费检查器每次处理一个 URL。若要做全站审计,可用 Screaming Frog 之类的桌面爬虫抓取——Google 的迁移指南也推荐此法——导出所有 3xx 响应,再在改写规则之前把最严重的链条送进检查器逐一确认。