301 和 302 重定向怎么选:Google 只把其中一个当成换地址

重定向该发 301 还是 302,决定的是哪个地址最后留在搜索结果里:Google 把永久码当成规范化信号,把临时码当成「老地址继续留着」。按场景的决策表、三条自检命令、以及出问题的三种样子。

改写与发布6 分钟读完1127 次阅读
301 和 302 重定向怎么选:Google 只把其中一个当成换地址

301 和 302 这两个重定向码的区别,不在访客落到哪里,而在最后哪个地址留在搜索结果里。两个码都把浏览器送到同一个页面,但只有永久那一档会告诉 Google「新地址应该成为规范地址」。给一次永久搬迁发了临时码,老地址就会一直留在结果里,不报错,你不改它就一直这样。

Google 对每个重定向码的处理,只有两句话

Google 的重定向文档把所有跳转方式分成两桶,每桶给一句行为描述。永久那一桶「Show the new redirect target in search results」,临时那一桶「Show the source page in search results」。差别就这一条,而且发生在索引流程里,不在浏览器里。

同一页还有更长的一句。永久:「Googlebot follows the redirect, and the indexing pipeline uses the redirect as a signal that the redirect target should be canonical」。临时:「Googlebot follows the redirect, but the indexing pipeline doesn't use the redirect as a signal that the redirect target should be canonical」。注意两种情况下 Googlebot 都会跟过去,两个码都不挡抓取,变的只是那个规范信号。

码或方式Google 当作结果里显示
301 永久移动永久新地址
308 永久移动永久新地址
meta refresh,0 秒永久新地址
302 found临时老地址
303 see other临时老地址
307 临时重定向临时老地址
meta refresh,大于 0 秒临时老地址

这张表里有两行反直觉。meta refresh 写 0 秒算永久、写成延迟的算临时 —— 也就是说五年前谁在一个标签里随手打的那个秒数,今天还在决定一个规范信号。另一行是 308 跟 301 排在一起,而不是跟 307 排在一起,尽管在 HTTP 规范里 307 和 308 才是保留请求方法的那一对。

按场景决定发哪个码

Google 给的规则只有一句:「Use permanent redirects when you're sure that the redirect won't be reverted.」下面这张表就是这句话套到独立站真正会做的那几种搬迁上。

场景发哪个为什么
整站 http 换 https301 或 308不可能再换回去
www 与非 www 二选一301 或 308同上,顺带消掉重复地址
老文合并进新文301老地址该停止参与排名
商品缺货,下月回来302老地址应当继续被收录
两个线上页面做对照测试302原页面要保住自己的位置
站点维护中都不发,用 503跳转的意思是内容搬走了
把登录用户送去别处302公开地址并没有变

表里唯一一行写「都不发」的是维护期。理由和这一整页是同一条:跳转这个动作本身在说「这个地址上的内容搬到别处去了」,而维护期什么都没搬走。把整站临时指向一个公告页,等于对每一个被抓到的地址各声明了一次搬迁,而这句声明和事实不符 —— 内容还在原地,只是这会儿拿不到。这一行之所以要写进表里,是因为它是全表唯一一个「正确答案不在这两个码里」的场景,而它偏偏又是最容易被随手发一个 302 打发掉的那个。

301 和 308 之间,在搜索这一侧没有区别可报 —— Google 自己的表把它们排在同一行。区别在 HTTP 本身:308 保留请求方法,POST 过去还是 POST;301 允许客户端把 POST 改成 GET。普通内容页你察觉不到。表单接口或者 API 路径上你会。

真正该躲开的是用 JavaScript 做跳转。官方的说法是「Only use JavaScript redirects if you can't do server-side or meta refresh redirects」,理由是「rendering may fail for various reasons」。服务端的码在页面被解析出第一个字节之前就定了;JavaScript 那种要等渲染成功才算数。

怎么查自己的跳转到底返回了什么

配置文件里写的,和线上实际返回的,是两件事,而只有后一件能被验证。三条命令,按这个顺序。

  1. 先单独看第一跳。curl -sI http://你的域名/ 打印状态行和 Location,不跟随任何跳转,看到的是你自己源站选的那个码,而不是整条链末尾的码。
  2. 再走完整条链。curl -sIL http://你的域名/ | grep -iE '^HTTP/|^location:' 按顺序列出每一跳。首页跳超过两次就值得看一眼;每一跳都是爬虫要付的一次请求。
  3. 抽查十个真实地址,别只查首页。老文章地址、老分类路径、带斜杠结尾的和不带的同一个地址。首页那条规则通常是被测过的,剩下的通常没有。

第二步的可粘版本,输出格式固定,跨站也能横向比:

for u in / /blog /blog/ /old-post-slug; do
  printf '%s  ' "$u"
  curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' "https://你的域名$u"
done

先读状态码那一列。列里的每个 302 都应该对应一个你能说出口的理由,几秒钟说不出来的,基本就是有人把 301 打错了。

一个跳转码是对未来的承诺,302 承诺的是你以后会改主意。

这件事出问题的三种样子

三种都有动手之前就能看见的症状。

症状成因怎么修
老地址几个月后还在结果里永久搬迁发了 302改成 301,再复验一次
一条链跳三次以上规则一年年叠上去把第一条规则直接指向终点
浏览器里跳,curl 里不跳用 JavaScript 做的跳转挪到服务端

最后一行值得单说,因为它是唯一一种会躲开多数人手边那个工具的。浏览器会老老实实跟着 JavaScript 跳过去,所以在测的人眼里页面一切正常;而 curl 以及任何读原始响应的东西,看到的是一个 200 和一页标记。这个落差正是「用一次请求去查,而不是用眼睛去看」的理由。

中间那一行是最安静的一种。跳转规则会一层层堆起来,因为加新规则的人不会去删老规则,而每一层单独看都是对的:http 换 https,然后非 www 换 www,然后老路径换新路径。三条正确的规则叠在一起,爬虫读一个页面要发四次请求。同一批面板上实测出来的跳数与状态码分布在 27 个首页的 http 跳 https 实测;改地址除了跳转之外还会连带砸坏什么,在 301跳转之外还会砸坏的四处

这一步在什么情况下不适用

三条边界,第一条最常绊人。

  1. 跳转救不了一个从来没被收录过的页面。老地址如果本来就没有任何排名,把 302 改成 301 搬的是一个值零的信号。花一下午之前,先去 Search Console 查一下那个老地址。
  2. Google 没有公布永久跳转多久会反映到结果里,这一页也不替它补一个数。有文档支撑的是信号的方向,不是它的速度,所以两周之后结果没变,不足以证明码写错了。
  3. 要下线的内容不该用跳转处理。那是另一个决定、另一组码,而把一个已删除的页面指回首页,恰恰是最容易让它被当成软错误的做法。

还有一条边界要说白:这整件事都不是排名技巧。把码写对,只是让你不丢掉已经挣来的那个地址,它不会额外加分。爬虫和答案引擎到达之后能拿这个页面做什么,那是 QueryWin 怎么运转 在管的事。

常见问题

301 比 302 对 SEO 更好吗?

永久搬迁用 301 更好,临时情况用 301 就是错的。Google 的文档把这个选择挂在规范化上:永久码让新地址成为规范地址,临时码让老地址留在结果里。脱离场景谈哪个更强没有意义。

302 会传递权重吗?

官方文档没有用「传递权重」描述跳转,它描述的是哪个地址成为规范地址。临时跳转把老地址留作被收录的那一个,所以留下来的那个地址仍然带着它原本的东西。

301 和 308 有什么区别?

搜索这边,Google 没有写出任何区别 —— 它俩在同一张表的同一行。HTTP 这边,308 保留请求方法,301 允许客户端把 POST 换成 GET。

跳转要保留多久?

比你以为的更久,因为老地址会永远留在别人的链接里。官方没有给过期时间,所以撤掉它应该是一个专门做的决定,不是清理任务顺手干掉的一项。

能不能用 meta refresh 代替?

Google 把 0 秒的当永久、把延迟的当临时,所以它能用;也正因为如此,一个被改错的秒数会悄悄改掉整件事的含义。服务端的码不会被内容编辑器里的人误改。

本文属于 QueryWin 实操手册 · 第 2 阶

301 和 302 重定向怎么选:Google 只把其中一个当成换地址