搜索全站
建站 12 分钟阅读

WordPress改版301重定向总表:逐条映射、规则写法与验证

改版后流量腰斩,多半是 301 没做全。本文讲清重定向总表的制作流程:导出旧 URL、逐条映射、Nginx 与插件两种落地方式、链式跳转排查与批量验证脚本。

U
UFO_PF 2020-03-21 · 阅读 12 分钟
Wo 建站
阅读提示
本文约 4,611 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:改版上线那天,流量掉了一半

改版通常是为了变得更好:新主题、新结构、更清晰的 URL。但上线一周后打开统计,自然搜索流量掉了 40%–60%,站长平台里”抓取异常”多出几百条,很多旧链接显示 404。这时候才想起来:旧站那些被收录、被引用、被收藏的 URL 已经不存在了,而搜索引擎需要时间把旧地址的权重转移到新地址,前提是它知道新地址在哪——这个”告诉它”的动作就是 301。

301 是永久重定向,它会把旧 URL 的权重信号传递给新 URL,并且让已收录的旧地址逐步被替换。做不全的代价很直接:旧地址 404,用户点进来是死路,搜索引擎抓到大量 404 会降低抓取效率,排名自然下滑。本文讲清如何系统地做一遍重定向映射,而不是凭记忆补几条。

原理分析:重定向要做的是”集合对集合”的映射

新手最常见的做法是”想到哪补到哪”:发现某篇 404 就补一条规则。这样做的问题是永远补不全——你不知道自己有多少条旧 URL,也就无法确认补完了没有。正确做法是把旧站和新站各自导出成两个 URL 集合,然后做集合对集合的映射,最后检查”未映射的旧 URL”这个差集。

映射关系有三种类型,处理方式不同:

类型 例子 处理方式
一对一 /old-a/ → /new-a/ 逐条写 301
多对一 旧站 5 篇短文 → 新站 1 篇合集 全部指向合集页(内容需真的包含)
无对应 旧内容已删除 返回 410 Gone,不要全指向首页

第三类最容易被错误处理。把删除的页面全部 301 到首页,搜索引擎会判定为”软 404″,效果比直接返回 404/410 更差。正确做法是内容确实删除且无替代的返回 410;有替代但不完全相关的,指向最相关的栏目页。

还要注意两类技术问题:一是链式跳转(A→B→C),每多一跳就多一份权重损耗和加载时间,应尽量拍平成 A→C;二是规则顺序,Nginx 的 rewrite 是按顺序匹配的,通用规则写在前面会把具体规则截胡。

保姆级实操

  1. 导出旧站全量 URL(这是最关键的一步)

三个来源合并去重:旧站数据库导出(wp post list)、站长平台的已收录地址、以及网站日志里出现过的真实请求路径。第三个来源最容易被忽略,但它包含所有真实被访问过的地址(包括你以为不存在的):

# 1) 旧站导出全部文章与页面的 URL 路径
wp post list --post_type=post,page --post_status=publish \
  --field=url --format=csv > old-urls.csv

# 2) 从访问日志里提取所有被请求过的 200 路径(去重后按次数排序)
awk '$9==200 {print $7}' /var/log/nginx/access.log \
  | sed 's/\?.*$//' | sort | uniq -c | sort -rn \
  | awk '{print $2}' > logged-urls.txt

# 3) 合并去重,得到待映射清单
cat old-urls.csv logged-urls.txt | sed 's#https\?://[^/]*##' \
  | sed 's#/$##' | sort -u > all-old.txt
wc -l all-old.txt
  1. 导出新站全量 URL,做映射表

同样方式导出新站 URL 到 all-new.txt,然后在一张表格里逐条映射。表格字段:旧 URL、新 URL、映射类型(1:1 / N:1 / 410)、备注。这张表就是”重定向总表”,建议用共享表格多人协作填写,一个人填容易漏。

  1. 按量选择落地方式

数量少(几十条以内)或经常变动,用 Redirection 插件(后台「工具 → Redirection」逐条添加,自动记录 404 便于补漏);数量多(几百上千条)或追求性能,直接写进 Nginx/Apache 配置,比数据库查询快得多:

# Nginx:一对一精确匹配用 location = 或 rewrite ... permanent
location = /old-a/ {
    return 301 https://mimangfei.com/new-a/;
}
location = /2019/05/old-post/ {
    return 301 https://mimangfei.com/jianzhan/wordpress-flow/;
}

# 带参数的旧地址(如 ?p=123)用 rewrite 保留查询串
rewrite ^/\?p=123$ /jianzhan/wordpress-flow/ permanent;

# 整块路径迁移(旧博客目录整体搬到新目录)用一条规则搞定
rewrite ^/blog/(.*)$ /jianzhan/$1 permanent;

# 已删除且无替代内容:返回 410,不要全跳首页
location = /promotion-2018/ {
    return 410;
}

# 注意:具体规则必须写在通用规则之前,否则会被截胡

Apache 环境写在 .htaccess 里,注意规则要放在 WordPress 自带的 # BEGIN WordPress 块之前:

# 放在 WordPress 重写规则之前
Redirect 301 /old-a/ https://mimangfei.com/new-a/
Redirect 301 /2019/05/old-post/ https://mimangfei.com/jianzhan/wordpress-flow/
RedirectMatch 301 ^/blog/(.*)$ /jianzhan/$1
Redirect gone /promotion-2018/
  1. 处理 WordPress 层面的兜底

极少量无法在服务器层配置的场景(比如虚拟主机不给改配置),可以用 PHP 在 template_redirect 上兜底,但只建议放少量规则,且要放在插件里而不是主题里(换主题不会丢):

<?php
// 少量兜底规则:只在 404 时才执行,避免影响正常页面
add_action( 'template_redirect', function () {
    if ( ! is_404() ) {
        return;
    }
    $map = array(
        '/old-a/'        => '/new-a/',
        '/2019/05/old/'  => '/jianzhan/wordpress-flow/',
    );
    $path = wp_parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
    if ( isset( $map[ $path ] ) ) {
        wp_safe_redirect( home_url( $map[ $path ] ), 301 );
        exit;
    }
}, 1 );
  1. 批量验证:逐条跑一遍看状态码

规则写完必须验证。写个脚本读映射表,逐条请求,断言返回 301 且 Location 正确、最终落地是 200:

#!/usr/bin/env bash
# verify-301.sh:读取映射表(旧URL 新URL 每行一对),逐条校验
while read -r old new; do
  [ -z "$old" ] && continue
  code=$(curl -s -o /dev/null -w "%{http_code}" "https://mimangfei.com${old}")
  loc=$(curl -s -o /dev/null -w "%{redirect_url}" "https://mimangfei.com${old}")
  final=$(curl -sL -o /dev/null -w "%{http_code}" "https://mimangfei.com${old}")
  if [ "$code" != "301" ] || [ "$loc" != "https://mimangfei.com${new}" ] || [ "$final" != "200" ]; then
    echo "异常: $old -> code=$code loc=$loc final=$final"
  fi
done < redirect-map.txt
echo "验证完成"
  1. 上线后持续补漏

打开 Redirection 插件的 404 日志(或定期分析访问日志里的 404 路径),每周补一次。同时在站长平台提交死链文件(百度搜索资源平台的死链提交功能),并观察”抓取异常”数量是否逐周下降。

常见踩坑

  • 把所有旧 URL 一股脑 301 到首页:被判定为软 404,效果比直接 404 更差,且用户被扔到首页后立刻跳出。
  • 案例:某站点改版时把重定向规则写在了 .htaccess 中 WordPress 规则块的后面,结果所有旧链接先被 WordPress 的 index.php 规则吃掉,统一返回 404,301 一条都没生效。排查了三天才发现是规则顺序问题——通用重写规则永远要放在最后。
  • 没处理带 www 与不带 www、http 与 https 的组合:四条变体各返回 200,形成四份重复内容,应先统一到一种形式后再做业务重定向。
  • 产生链式跳转:旧 → 中间 → 新,中间地址是上一次改版留下的。应定期用 curl -IL 看跳转链,把链拍平。
  • 忘了重定向图片和附件地址:文章通了但图片全是 404,用户体验照样崩。
  • 用 302 而不是 301:临时重定向不传递权重,等于白做。
  • 改完没更新站内链接:站内还链着旧地址,每次点击都多一次跳转,也浪费抓取预算。

总结

改版重定向的判断标准是两条:旧 URL 的映射覆盖率是否接近 100%(用差集检查,而不是凭感觉),以及有没有链式跳转。前者靠导出清单做集合映射,后者靠 curl -IL 逐条验证。整个工作的核心在第一步——把旧站全量 URL 导出来;没做这一步,后面所有补漏都是碰运气。改版完成后,配合 冷启动新站的 90 天内容计划 重新规划内容节奏,用 网站数据分析基础指标 观察流量恢复曲线,通常 4–8 周能回到改版前水平。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。