URL 改了之后收录全掉:301 重定向链的隐形代价与网站迁移的正确姿势

URL 改了之后收录全掉:301 重定向链的隐形代价与正确迁移姿势

个人站长做 SEO 最常踩的一个坑,不是忘记写 title,也不是外链不够,而是改 URL 结构。老文章从 /archives/123.html 换成 /linux-nginx-502.html,你觉得这是"优化",结果两周后搜索流量对半砍,Site 里满屏"已发现未编入索引",旧链接点进去 404。

这篇文章不讲"要写 301 重定向"这种人人都知道的话。我要讲的是 301 背后真正影响收录的三个机制:重定向链的长度权重传递的损耗、以及搜索引擎重新抓取的时间成本。搞懂这三点,你才知道为什么有的站长迁移后一周恢复,有的三个月都没缓过来。

先搞清一件事:301 不是"把权重原样搬过去"

很多人把 301 想象成搬家,家具原样搬运。真实机制更接近"换地址后通知邮局"。搜索引擎看到 301,会做三件事:

第一,把新 URL 排进抓取队列,等爬虫来抓。第二,在算法层面逐步把旧 URL 的信任度转移到新 URL。第三,继续在相当长一段时间内保留旧 URL 的索引,因为搜索引擎不确定这个跳转是永久的还是临时的。

关键在于第二点的"逐步"。这个转移不是一次完成的,而是随多次抓取慢慢累积。所以改 URL 之后第一周排名掉一半是正常现象,不代表你做错了。真正的错误信号是:三周后依然没有回升趋势,或者旧 URL 迟迟不被替换。

重定向链:多少站长栽在这条"看似无害"的链上

看一个真实的高频错误配置:

# 第一跳:http 到 https
server {
    listen 80;
    return 301 https://example.com$request_uri;
}
# 第二跳:裸域到 www
server {
    listen 443 ssl;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}
# 第三跳:旧路径到新路径
location = /archives/123.html {
    return 301 https://www.example.com/linux-nginx-502.html;
}

访问 http://example.com/archives/123.html 会经历三次跳转:http→https、裸域→www、旧路径→新路径。看起来每一步都"合理",但组合起来就是一条三重跳转链。

重定向链的代价是双重的。其一是抓取预算浪费:爬虫每一次跳转都要单独发一次请求,三次跳转就是三次抓取额度,而服务器的抓取预算是有限的(这个预算跟站点权重正相关,新站预算很小)。其二是权重损耗:虽然官方说法是 301 传递绝大部分权重,但链条越长,传递过程中的不确定性越大,实践中三重链相比单跳链明显恢复更慢。

正确的做法是把跳转合并到一跳。让所有入口(http/裸域/旧路径)直接 301 到最终目标:

server {
    listen 80;
    server_name example.com www.example.com;
    # http 且非 www 的情况,直接跳到最终 https+www
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    # 裸域 https,直接跳到 www
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name www.example.com;
    # 最终站,处理路径级重定向
    location = /archives/123.html { return 301 /linux-nginx-502.html; }
}

注意第三段的写法:跳转目标是相对路径 /linux-nginx-502.html 而不是完整的绝对 URL。这样做的好处是 Nginx 不会再产生一次协议/域名的规范化判断,跳转一步到位。同时前两段用 $request_uri 保留原始路径,确保 http 访问旧路径时能直接落到正确的最终地址(虽然仍经过两次跳转,但这是协议和域名规范化的必要成本,无法省略)。

如何检测站点上到底有几条重定向链

不要靠肉眼看配置,直接测。用 curl 跟踪全部跳转:

curl -sIL "http://example.com/archives/123.html" | grep -iE '^HTTP|^location'

输出里每一行 HTTP/ 代表一跳到访。理想情况是:从任何入口出发,最多两跳到达最终页面(一跳是协议规范化,一跳是旧路径改写)。如果出现三跳以上,立刻合并。

批量检查全站旧链接更实用的写法,是从 Nginx 访问日志里把历史 301 找出来,按跳转目标聚合,找出被多次中转的路径

awk '$9 == 301 {print $7, $11}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn | head -20

(注意 log_format 里需要包含 $sent_http_location 才能看到跳转目标,默认格式里没有,需要在 http 块里自定义。)

路径级重定向最容易出错的地方:查询参数与大小写

改 URL 时很多人忽略了旧链接上挂着参数。比如旧链接常带 ?utm_source=xxx 或分页参数 ?page=2。如果重定向规则用了精确匹配:

location = /archives/123.html { return 301 /new-path.html; }

那么 /archives/123.html?page=2 也会被跳到 /new-path.html参数被丢掉。更糟的是,如果旧站有大量带参数的链接,搜索引擎可能把它们当作独立 URL 处理,你丢掉的不只是路径权重,还有这些参数页积累的信号。

正确做法是用前缀匹配把参数保留下来:

location ~ ^/archives/123\.html$ {
    return 301 /new-path.html$is_args$args;
}

$is_args 在有查询串时输出 ?,无则输出空;$args 是原始查询串。这一对组合是 Nginx 里保留参数的标准写法。

另一个高频坑是大小写。旧链接如果出现过 Archives/123.HTML 这种混合大小写(有的老旧 CMS 生成过),精确匹配会漏掉。要么用 ~* 做不区分大小写的正则匹配,要么在服务端统一做小写规范化 —— 后者更好,因为搜索引擎对大写 URL 的索引本身就是个隐患。

旧 URL 到底该 301、410 还是保留?

这是迁移决策里最容易被一刀切的问题。三类情况处理方式完全不同。

情况一:内容只是换了路径,内容本身还在。用 301 到对应的新地址。这是最理想的情况,权重可以转移。

情况二:内容合并了。比如你把三篇短文章合并成一篇长文,旧 URL 的 301 目标应该是那篇合并后的长文,而不是首页。指向首页的 301 会被搜索引擎当作"软 404"处理 —— 它认为你没给用户对等的内容,权重大概率不传递。

情况三:内容彻底删除,没有对等替代。用 410 Gone,不要用 301 到首页,也不要用 404 挂着。410 明确告诉搜索引擎"这个资源永久消失了",它可以更快地把 URL 从索引里移除,释放抓取预算。用 404 的话,搜索引擎会持续试探抓取好几个月,白白消耗预算;用 301 到首页则可能被判为作弊性重定向。

# 内容删除,明确告知
location = /old-deleted-article.html { return 410; }

迁移操作的正确时序:先建映射,再改,最后提交

顺序错了,恢复时间会成倍增加。推荐流程:

第一步,建立完整的旧新 URL 映射表。不要边改边想。从 sitemap.xml、Nginx 访问日志、数据库里的 permalink 三处取并集,形成一份 old_path new_path 的映射文件。这份文件后面要用来验证覆盖率。

第二步,先在 Nginx 里把所有 301 规则配好并测试通过,再动站点本身的 URL 结构。这样在切换的瞬间,旧链接就已经能正确跳转,不存在 404 窗口期。nginx -t 验证语法后 nginx -s reload(reload 不中断连接)。

第三步,验证映射覆盖完整。拿映射表里的每一个旧路径跑一遍 curl -sI,确认返回 301 且目标正确。这一步必须脚本化,手工抽检一定会漏。

while read -r old new; do
  code=$(curl -s -o /dev/null -w '%{http_code}' "https://example.com$old")
  loc=$(curl -sI "https://example.com$old" | grep -i '^location' | tr -d '\r')
  echo "$code $old -> $loc"
done < redirect_map.txt

第四步,提交新的 sitemap 并更新内部链接。站内的所有内链(导航、相关阅读、正文里的链接)必须指向新 URL,不能让用户和爬虫走 301 中转 —— 内链走旧地址会让重定向链重新出现。

第五步,保留旧重定向至少一年。不要因为"已经恢复了"就把 301 规则删掉。外链、用户书签、搜索引擎缓存里到处都是旧地址,删掉规则它们立刻变 404。

迁移后的监测指标:看什么、不看什么

改完之后每天看两个数:新 URL 的索引数量旧 URL 的抓取状态。不要盯着总流量看,那个指标在迁移期波动剧烈且滞后,会让你做出错误决策。

判断恢复是否健康的信号:新 URL 索引数稳步上升;旧 URL 逐渐从"已编入索引"变成"已替换为其他规范网址";站点地图提交后被抓取的比例回升。这三个趋势同时出现,说明迁移走在正轨上,剩下的是时间问题。

要做警报的信号:旧 URL 大量显示"重定向错误"或"已发现未编入索引"且数量持续增长;新 URL 索引数长期不动;服务器日志里 301 的数量远高于 200。后者尤其说明站内还有大量链接在走旧地址,需要排查内链改造是否彻底。

# 快速看站内 301 占比
total=$(grep -c '' /var/log/nginx/access.log)
moved=$(awk '$9 == 301' /var/log/nginx/access.log | wc -l)
echo "301 占比: $(awk "BEGIN{printf \"%.1f%%\", $moved/$total*100}")"

健康的站点这个比例应该很低(通常个位数百分比),因为绝大多数请求都应该直接命中最终 URL。如果三成以上的请求都在走 301,那你的内链改造基本等于没做。

一句话总结

改 URL 的风险不在于"该不该改",而在于跳转链的长度参数的保留映射的完整性内链的同步改造这四件事。把 301 规则在切换前配好、测试好,用脚本验证每个旧路径都能一跳到达正确目标,保证站内不再产生新的跳转请求 —— 做到这四点,你的迁移基本就是干净的,剩下的交给搜索引擎重新抓取即可。

Last modification:September 24th, 2026 at 09:26 pm

Leave a Comment