做网站的人都有这种经历,文章发多了,链接和锚文本乱七八糟,一个个手动去改简直要命。DEDECMS后台没有提供批量替换功能,但不代表没别的路子。今天就把我实际用过的几个方法分享出来,都是经过验证的。
先说最省事的办法。DEDECMS后台的数据库备份功能其实自带SQL执行入口,只是很多人没注意。进入后台,点“系统”菜单,找到“SQL命令行工具”,这里可以直接执行SQL语句。比如你想把所有指向旧域名的链接换成新域名,写一条UPDATE语句就行:
UPDATE dede_addonarticle SET body = REPLACE(body, ''www.old-domain.com'', ''www.new-domain.com'');
这条语句会把所有文章正文里的旧域名替换成新域名。注意表名前缀,如果你安装时改过前缀,要对应修改。我一般习惯先备份数据库再执行,万无一失。
但SQL替换有个坑,锚文本和链接是分开处理的。如果你只想改锚文本文字,不改链接,或者反过来只改链接不改文字,用REPLACE函数就没那么精准了。这时候需要用正则表达式,DEDECMS的SQL命令行支持REGEXP_REPLACE吗?实际上要看MySQL版本,5.7以下不支持。我用的办法是写PHP脚本,通过DEDECMS的include/common.inc.php加载环境,然后遍历文章表,用preg_replace处理。

具体做法:新建一个PHP文件放在网站根目录,写个循环查询dede_addonarticle表,取出body字段,用正则匹配a标签。比如把所有的“旧关键词”锚文本换成“新关键词”,同时保留原来的链接地址。正则大概是这样的:
preg_replace(''/]*href="([^"]*)"[^>]*>旧关键词<\/a>/'', ''新关键词'', $body);
这招比较灵活,改完以后删除这个PHP文件,别留在服务器上惹麻烦。
还有一个更简单粗暴的方法,用phpMyAdmin。如果你是虚拟主机用户,主机商一般都会送phpMyAdmin管理入口。登录进去,选择你的数据库,找到dede_addonarticle表,点“SQL”标签页,执行同样的UPDATE语句。好处是能看到影响行数,改了多少条一目了然。我上次帮客户改了三千多篇文章,用了不到三秒。
要是文章数量特别大,几万篇那种,建议分批处理。MySQL的REPLACE函数是全表扫描,数据量太大容易超时。可以在SQL后面加LIMIT限制,比如每次处理一千条,循环执行。但要注意怎么定位“未处理”的记录,我通常加一个custom_field字段标记,处理过的打个标记,下次查询就跳过。
DEDECMS后台还有个“系统基本参数”里的“文档内容关键字替换”功能,默认是关闭的。打开以后,可以设置替换规则,前台生成的时候自动替换,不用改数据库。但这个方法有个坑,只在生成静态页时生效,如果你用的是动态浏览模式就没用,而且特别消耗资源,不推荐多用。
采集的文章里经常有各种推广链接和乱七八糟的锚文本,处理起来最头疼。用SQL替换的话,得先查清楚都有哪些链接。可以先运行一条查询语句看看到底有多少个不同链接:
SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(body, ''href="'', -1), ''"'', 1) AS link FROM dede_addonarticle;
这样能把所有文章里的链接列出来,再决定替换策略。比瞎猜强多了。
对了,改完以后记得更新文档缓存。DEDECMS有内容缓存机制,数据库改了但旧缓存还在,前台显示的还是老样子。可以在后台“系统”里点“更新缓存”,或者运行SQL清空缓存表。具体是哪个表忘了的话,直接把dede_arccache表里的数据DELETE掉就行。
还有一点,批量替换之前一定要把网站设为“关闭状态”,不然一边改人家一边访问,容易出问题。改完以后测试几篇文章,确认没问题再打开。我有一次没设关闭状态,改到一半有读者评论,结果评论时间都乱了,折腾好久才恢复。
最后提醒一句,这些操作只对文章正文有效。如果你还要改标题里的链接,或者自定义字段里的内容,得额外处理。方法是类似的,查一下哪些表哪些字段存放了这些数据,再逐个替换。反正记住一个原则:先备份,再操作,出错了能悔棋才是王道。