改域名/换结构后收录暴跌,问题往往出在改之前
我见过太多站长,辛辛苦苦攒了几百个收录、几千 IP 的流量,结果改一次域名或者调整一次 URL 结构,一个月后流量掉了一半。他们通常的复盘是"搜索引擎对新站有考核期",但真实原因往往是:301 跳转没做全、旧链接没有兜底、站内链接没更新,搜索引擎爬到的是一堆死链接,自然就把权重收回去了。
网站迁移(换域名、改 URL 结构、从 HTTP 换 HTTPS、WordPress 换 Typecho 这类 CMS 迁移)是站长绕不开的操作,但它是少数几个"做错一步、损失不可逆"的事项。这篇文章把迁移不丢权重的完整操作流程拆开讲清楚,从迁移前的链接盘点,到 301 规则设计,再到迁移后的收录监控,每一步都有可落地的命令和检查清单。
第一步:迁移前先做链接资产盘点
迁移最忌讳的就是"边改边想"。动手之前,你必须先搞清楚自己有哪些 URL 是搜索引擎已经收录、已经给权重的。
从搜索引擎要数据。登录 Google Search Console,在"页面"报表里导出所有有展示、有点击的 URL;百度搜索资源平台里看"索引量"和"抓取频次"。这些被收录的 URL 就是你的核心资产,一个都不能丢。
从自己的网站要数据。如果你能访问服务器,最准确的方法是直接从访问日志里提取所有被访问过的 URL:
# 提取 Nginx access.log 中所有被访问过的 URL 路径,去重排序
awk '{print $7}' /var/log/nginx/access.log | sort -u > all_urls.txt
wc -l all_urls.txt这个方法能揪出搜索引擎 Sitemap 里没有、但实际被抓过的长尾 URL,非常实用。
从 Sitemap 要数据。如果你有 sitemap.xml,把里面所有 URL 也整理出来,和上面两个来源合并去重,就得到一份完整的"迁移前 URL 清单"。这份清单是后面做 301 映射的底稿,务必保存好。
第二步:设计新旧 URL 的映射关系
有了旧 URL 清单,接下来要为每一个旧 URL 找到它对应的新 URL,形成"旧→新"的映射表。根据迁移类型不同,映射规则也不一样。
情况一:只换域名,URL 路径不变
这是最简单也最幸运的情况。old.com/post/123 变成 new.com/post/123,路径完全一样。这种迁移只要在旧域名的 Nginx 里做一条全站 301 即可:
server {
listen 80;
listen 443 ssl;
server_name old.com www.old.com;
# 保留原路径,只换域名
return 301 https://new.com$request_uri;
}注意 $request_uri 包含了路径和查询参数,这样 old.com/post/123?page=2 会被正确跳转到 new.com/post/123?page=2,不会丢失参数。
情况二:URL 结构变了
比如从 old.com/?p=123(动态参数)改成 new.com/nginx-limit-req-tutorial/(静态伪静态),或者 Typecho 换固定链接格式。这时没法用一条通配规则搞定,必须逐条映射。可以在 Nginx 里用 map 或者大量 rewrite 规则:
# 方式一:逐条 rewrite(适合数量不多、规则不规则)
rewrite ^/old-article-1\.html$ /nginx-limit-req-tutorial/ permanent;
rewrite ^/old-article-2\.html$ /redis-persistence-guide/ permanent;
# 方式二:rewrite 配合正则批量处理
rewrite ^/article/(\d+)\.html$ /post/$1/ permanent;这里要强调一个铁律:301 必须是一一对应的,绝不能让所有旧链接都跳到首页。搜索引擎对"全站跳首页"的处理是把它当成作弊或失效处理,会直接丢掉这些页面的权重。宁可多写几百条规则,也不要图省事跳首页。
用 Python 批量生成 301 映射表
如果旧 URL 有几百上千条,手工写规则不现实。我通常用一段脚本,把旧的数字 ID 和新的 slug 按数据库对应关系生成 Nginx 配置:
import pymysql
conn = pymysql.connect(host='localhost', user='root',
password='xxx', db='mysite')
cur = conn.cursor()
cur.execute("SELECT cid, slug FROM contents WHERE type='post'")
lines = []
for cid, slug in cur.fetchall():
# 旧链接是 /archives/{cid}/,新链接是 /{slug}/
lines.append(
f"rewrite ^/archives/{cid}/?$ /{slug}/ permanent;"
)
with open('/etc/nginx/conf.d/redirects.conf', 'w') as f:
f.write('\n'.join(lines))
print(f"生成 {len(lines)} 条 301 规则")生成后记得 nginx -t 校验语法,再 systemctl reload nginx 生效。
第三步:别忘了这些"隐形链接"
很多人只改了页面之间的 301,却漏掉了下面这些同样会被搜索引擎抓取的地方,结果权重平白流失:
Sitemap.xml。迁移后立刻更新 Sitemap,把新 URL 全部替换进去,同时在 Search Console 和百度资源平台重新提交。旧 Sitemap 可以保留一段时间,但内容必须是 301 后的新地址。
robots.txt。如果旧域名要彻底废弃,可以在旧站 robots.txt 里放行所有抓取、让它能顺利读到 301;如果新站还在建设,千万别用 Disallow: / 挡住搜索引擎,这是新手常犯的致命错误。
canonical 标签。检查新页面的 指向的是新 URL,而不是残留的旧 URL。canonical 指向错误会让搜索引擎把两个地址当成重复内容。
内部链接。站内文章里指向旧链接的锚文本要全部替换成新链接。搜索引擎会顺着内部链接爬行,如果内部还大量指向旧地址(哪怕有 301),也会浪费爬虫预算、拉长收录周期。这一步可以用批量替换搞定:
# 在数据库里批量替换正文中的旧域名
mysql -uroot -p dbname -e "
UPDATE contents
SET text = REPLACE(text, 'https://old.com', 'https://new.com')
WHERE text LIKE '%https://old.com%';
"外链和社交媒体。你能控制的外部链接(友链、社交主页、广告位)尽量更新成新地址,不能控制的(别人转载的文章)就靠 301 兜底。
第四步:迁移后必须做的收录监控
301 配好、Sitemap 提交,不代表结束。迁移后的 2~6 周是关键观察期,要盯住几个指标:
看新域名收录量。Search Console 的"已编入索引"页面数应该缓慢上升,逐步接近旧域的收录量。百度资源平台看"索引量"曲线,正常是平稳迁移或者略微下探后回升。
看抓取错误。Search Console 的"页面"报表里如果出现大量 404,说明有旧链接没有覆盖到 301,赶紧补上。404 集中在哪个路径,就说明哪一批规则漏了。
看 301 是否真的生效。用 curl 逐个抽查,确认返回码和 Location 头正确:
curl -sI "https://old.com/archives/123/" | grep -iE "^(HTTP|location)"正确输出应该是 HTTP/2 301 加上 location: https://new.com/xxx/。如果返回 200,说明 301 没配;如果返回 302,搜索引擎会怀疑你只是临时跳转,权重转移会大打折扣——永久迁移一定要用 301,不要用 302。
几个一定要避开的坑
坑一:301 跳转链。A → B → C 这种多级跳转会稀释权重,搜索引擎明确建议把 301 指向最终目标,不要出现跳转链。迁移时最好一步到位。
坑二:老域名的 301 只能保留一段时间?这是流传很广的误解。301 只要还有外链指向旧域名,就应该一直保留。我见过有人迁移一年后关掉旧域名的 301,结果外链权重断了,流量应声下跌。除非旧域名彻底不续费了,否则 301 长期挂着没有坏处。
坑三:新旧内容不一致。如果迁移的同时还改了页面内容,搜索引擎很难判断这是同一个页面,权重转移会更慢。建议迁移和改版分开做,先稳定迁移,过一两个月再优化内容。
坑四:忘了 HTTPS。如果迁移顺带从 HTTP 换 HTTPS,要确保旧的 HTTP 地址 301 到新的 HTTPS 地址,而不是 HTTP 内部 301 一次再来一次。全站只允许一次跳转。
小结:迁移的本质是"帮搜索引擎认路"
网站迁移不丢权重的核心逻辑,其实只有一句话:让搜索引擎在任何一个旧地址上,都能一步顺畅地找到新地址,并且确认这是同一个页面。做到这一点,需要迁移前盘点链接资产、迁移中做好一一对应的 301、迁移后盯紧收录曲线。任何一个环节偷懒,代价都是流量。
对个人站长来说,站点是一点一滴做起来的,迁移这种不可逆的操作,宁可多花两天做足准备,也不要抱着"应该没事"的心态直接上线。把上面的清单当成 checklist 走一遍,你的权重就能安全搬过去。
附:一份可直接套用的迁移 checklist
把前面所有内容浓缩成一份可以在迁移当天逐项打勾的清单,建议收藏:
迁移前(提前 3~7 天):
1. 导出 Search Console 与百度资源平台的全部已收录 URL;
2. 从 Nginx access.log 提取历史访问 URL,与 Sitemap 合并,形成旧 URL 总清单;
3. 确认新站内容与旧站一一对应,页面标题、正文不要大改;
4. 备份旧站数据库和全部文件,确保可回滚。
迁移当天:
5. 在新站上线全部内容,先用临时域名或 hosts 绑定验证页面正常;
6. 生成旧→新的 301 映射规则,nginx -t 校验后 reload;
7. 更新新站 Sitemap、canonical、robots.txt;
8. 批量替换站内正文和模板里的旧域名。
9. 逐个抽查 301:curl -sI 确认返回 301 且 Location 正确。
迁移后(持续 4~6 周):
10. 在 Search Console 和百度资源平台提交新 Sitemap,使用"地址更改"工具;
11. 每周查看收录量、抓取错误、404 报告;
12. 发现 404 立即补 301,不要拖延;
13. 观察关键词排名与流量曲线,2~4 周后应趋于平稳。
再补充一个容易被忽略的细节:HTTPS 证书
如果迁移涉及换域名,新域名的 HTTPS 证书必须提前签好并验证无误,否则迁移当天搜索引擎来抓取时遇到证书错误,会直接中断抓取。用 acme.sh 或 certbot 给新域名签发好证书后,用下面的命令验证证书链完整、域名匹配:
echo | openssl s_client -connect new.com:443 -servername new.com 2>/dev/null | openssl x509 -noout -subject -dates如果输出里能看到正确的 CN 和有效期,说明证书没问题。另外别忘了配置 HTTP→HTTPS 的 301,避免出现"HTTPS 证书过期 → 用户看到警告页"这种最劝退的体验。
还有个细节:如果旧域名和新域名同时都开着 HTTPS,要确保旧域名的证书也在有效期内。很多人迁移后就不再续费旧域名的证书,结果旧域名的 301 因为证书报错失效,等于白做。旧域名只要还在承担 301 职责,它的证书就必须保持有效。
总结
网站迁移与其说是技术活,不如说是细致活。技术方案本身不复杂——301、Sitemap、canonical、内链替换,都是标准动作,难的是不漏、不错、有耐心。搜索引擎给你的容错空间很小,一次全站跳首页、一批漏掉的 301、一个指向旧地址的 canonical,都可能让几个月积累的权重大打折扣。照着上面的流程和清单走,把每一步都验证到位,迁移就只是换个域名而已,流量该是你的还是你的。