DedeCMS转Typecho迁移完整指南:批量脚本+SEO保稳47步+11类避坑

DedeCMS转Typecho迁移完整指南:批量脚本+SEO保稳47步+11类避坑

完整DedeCMS到Typecho迁移方法:PHP批量脚本(已实测六次最大8.7万篇)、Nginx伪静态、301重定向map写法、字符集GBK转utf8mb4、SEO保稳监测,附二十四小时复盘清单。

张文保 更新 40 分钟阅读 1,480 阅读
本文目录
  1. 为什么要弃用DedeCMS转到Typecho
  2. DedeCMS的漏洞史与官方现状
  3. 为什么选Typecho而不是WordPress
  4. 性能对比的实测数据
  5. 迁移前的准备工作
  6. 数据库信息确认
  7. 环境依赖检查
  8. 目标系统就绪
  9. 双向数据备份
  10. 内容预处理与图片路径规划
  11. 权限检查
  12. 迁移工具的核心设计与完整代码
  13. 工具的六个核心优势
  14. 完整迁移脚本
  15. 迁移后的关键配置
  16. SEO保稳的核心动作
  17. 4.1 301重定向规则的完整写法
  18. sitemap.xml的提交与索引保稳
  19. 内链与目录结构的SEO权重保留
  20. 主题的SEO优化要点
  21. 迁移后的注意事项与验证
  22. 数据完整性核对
  23. 字符集陷阱
  24. 调试模式必须关闭
  25. 性能调优与缓存
  26. 监测与异常告警
  27. 实战中遇到的典型问题
  28. 标签数据丢失
  29. 自定义字段未迁移
  30. 评论数据丢失
  31. 文章作者归属错误
  32. 图片防盗链失效
  33. 迁移之后的SEO持续优化
  34. 内容质量重做
  35. 内链结构重构
  36. 结构化数据补全
  37. 性能持续优化
  38. 常见问题解答
  39. 迁移后原DedeCMS的URL如何301到Typecho?
  40. 多作者站点怎么改作者ID硬编码?
  41. 迁移后内部链接失效怎么批量修复?
  42. PHP版本8.2兼容这套脚本吗?
  43. 怎么把DedeCMS的自定义字段也迁过去?
  44. 评论数据能不能迁过去?
  45. PDO MySQL扩展未启用怎么办?
  46. 二级分类层级会不会混乱?
  47. Typecho后台媒体管理看不到图片怎么办?
  48. DedeCMS的数据库和文件还要保留吗?

保哥最近在给一个老客户排查网站异常,发现这个用织梦DedeCMS搭的站点被上传了加密木马、被篡改了内容,百度索引清零,多个安全平台标红。这个站点跑了十二年DedeCMS,期间经历过五次大漏洞被利用、三次写shell事件——彻底没必要再继续。最终我帮客户把数据迁到Typecho,从评估到上线总共花了四天,迁完一周百度恢复索引,三个月后流量回到了被黑前的水平。下面这篇是把全流程总结成的可复制方法,附完整迁移脚本和踩坑笔记。这套脚本我自己用过六次,迁过的最大站点是8.7万篇文章。

为什么要弃用DedeCMS转到Typecho

DedeCMS的漏洞史与官方现状

DedeCMS最后一次官方安全更新停在2021年11月(v5.7.106),距今已经四年没有正式补丁。这期间CNVD/CVE收录的DedeCMS高危漏洞超过47个,其中可远程执行代码的就有11个。常见的几个:dede/article_add.php任意文件上传、dede/co_do.php任意文件包含、include/dialog/select_soft_post.php上传绕过、plus/recommend.php SQL注入、tpl.php模板木马写入。这些漏洞修复都需要二次开发能力,普通站长根本守不住。

2022年7月织梦官方发布商业授权声明,要求所有商业用途必须购买授权(约5800元起),未授权使用面临版权诉讼。这进一步压缩了DedeCMS的使用空间。我手上有客户被代理律师函索赔过,最后协商付了2万8和解。

为什么选Typecho而不是WordPress

从DedeCMS迁出有三个常见选择:Typecho、WordPress、Halo。我自己的选型逻辑:

选WordPress的场景:内容量大(5万篇以上)、需要丰富的插件生态、有专人运维、不在意性能开销。WordPress生态最完善,但默认配置下性能差,需要装W3 Total Cache或者LiteSpeed Cache才能跑得动,主题市场鱼龙混杂。

选Typecho的场景:内容量在10万篇以内、追求性能和简洁、有一定开发能力、注重SEO控制粒度。Typecho核心代码只有2.7MB(WordPress约75MB),默认配置下首屏加载时间比WordPress快3到5倍,TTFB通常在200到400毫秒。我自己运营的zhangwenbao.com就是Typecho,从2018年用到现在五年多,稳定性远胜WordPress。

选Halo的场景:技术栈是Java、需要复杂的工作流、追求现代化的管理后台。Halo是国产新一代博客系统,但生态还在建设中,主题和插件数量不如Typecho丰富。

我给这个客户最终选Typecho的原因:他的内容量2.3万篇、运维只有他一个人、原DedeCMS主题简洁不需要复杂工作流。Typecho完美匹配。

性能对比的实测数据

我在同一台2核4G的腾讯云CVM上做过对照测试,相同的2.3万篇文章规模:DedeCMS默认配置首页TTFB 1.4秒、详情页TTFB 1.1秒、首页LCP 4.2秒;Typecho 1.3.0配置MySQL pagecache首页TTFB 280毫秒、详情页TTFB 220毫秒、首页LCP 1.6秒。同样的服务器配置,Typecho的Core Web Vitals表现完胜。

迁移前的准备工作

数据库信息确认

这一步看似简单但常踩坑。需要准确获取四组信息:DedeCMS数据库连接(host/user/pass/dbname/prefix)、Typecho数据库连接(同样四项加prefix)。表前缀默认值:DedeCMS是dede_、Typecho是typecho_,但如果安装时改过自定义前缀必须对应修改。

数据库主机地址通常是localhost(DedeCMS和Typecho在同一台服务器);如果跨服务器迁移,要确保MySQL允许远程连接(bind-address=0.0.0.0且防火墙开放3306端口)。我建议跨服务器场景下,先用mysqldump把DedeCMS数据库整库dump出来,导入到Typecho同一台服务器的临时库,这样脚本走localhost更快更稳定。

环境依赖检查

PHP版本:推荐7.4或8.2(PHP 8.0之后有不少废弃警告,需要在脚本顶部加屏蔽)。必须启用的扩展:PDO MySQL、mbstring、json、curl(图片下载时用到)。检查命令:在SSH里跑php -m | grep -E "pdo_mysql|mbstring|json|curl",应该看到四行输出。

内存配置:迁移脚本在脚本顶部用ini_set设置了memory_limit=512M,但php.ini本身的限制如果是128M也会拦截。需要确认php.ini里memory_limit至少设置为256M,max_execution_time至少3600秒。Nginx侧也要确认fastcgi_read_timeout在3600秒以上,否则脚本跑到一半被Nginx 504掐断。

目标系统就绪

Typecho必须先完整安装好,数据库表已经初始化。建议先发1到2篇测试文章验证安装无误,然后再开始迁移。Typecho版本推荐1.3.0(2024年12月发布,PHP 8.2兼容),1.2.1及以下版本的评论URL有XSS漏洞需要尽快升级。

主题先选一个跟原DedeCMS主题接近的避免视觉差异过大;插件先装:Sitemap(生成sitemap.xml)、CustomRSS(保留原RSS订阅地址)。不要一上来就装一堆插件,迁移完稳定运行一周后再按需添加。

双向数据备份

迁移前必须双向备份。命令模板:mysqldump -u root -p --single-transaction --routines dedecms 大于 dede_backup_20260511.sql;mysqldump -u root -p --single-transaction --routines typecho 大于 typecho_backup_20260511.sql。--single-transaction保证一致性快照、--routines同时备份存储过程。备份文件下载到本地一份+保留服务器一份+异地备份一份,三份至少存留三个月。

文件层备份:DedeCMS整站打包tar.gz压缩、Typecho站点目录也打包一份。如果空间紧张,Typecho可以只备份config.inc.php和usr目录。

内容预处理与图片路径规划

DedeCMS默认图片存在/uploads/目录下;Typecho默认在/usr/uploads/。两个方案:

方案A:保留DedeCMS的/uploads/路径,把整个目录复制到Typecho网站根目录的/uploads/下,迁移脚本里不替换路径。优点是文章里所有图片链接保持原样、不需要批量改写;缺点是Typecho后台媒体管理看不到这些图片(不在/usr/uploads/)。

方案B:把/uploads/目录复制到/usr/uploads/下,迁移脚本里启用str_replace替换。优点是符合Typecho规范、后台能管理;缺点是需要批量改写所有文章内容。

我推荐方案A——保留原路径风险最小,SEO友好(URL完全不变),Typecho后台看不到不影响实际访问。

权限检查

数据库用户权限是常见坑。最小权限要求:对DedeCMS数据库SELECT+SHOW VIEW、对Typecho数据库SELECT+INSERT+UPDATE+CREATE TEMPORARY TABLES。授权SQL:GRANT SELECT, SHOW VIEW ON dedecms.* TO 'migrator'@'localhost'; GRANT SELECT, INSERT, UPDATE, CREATE TEMPORARY TABLES ON typecho.* TO 'migrator'@'localhost';

建议为迁移单独建一个数据库账号migrator,迁移完之后REVOKE所有权限。这是安全最小化原则——长期共用root账号风险大。

迁移工具的核心设计与完整代码

工具的六个核心优势

调试友好:开启error_reporting(E_ALL)输出详细日志,每篇文章迁移进度、分类复用情况、跳过原因都打印,方便实时监控和排查。

数据库操作规范:用PDO连接+异常处理(ERRMODE_EXCEPTION)避免SQL注入风险,禁用预处理模拟(EMULATE_PREPARES=false)提升稳定性。

分类迁移智能:自动检测Typecho中已存在的分类,名称一致则复用,否则创建新分类,减少重复数据。

分批处理:通过pageSize(默认100)和offset实现分批迁移,配合延长的执行时间(3600秒)和内存限制(512M),适合处理大量数据。

冲突处理机制:把DedeCMS文章的aid作为Typecho的slug,保证URL结构不变,slug冲突时跳过并记录。

字符集兼容:连接字符串指定utf8mb4,支持emoji等特殊字符,避免迁移后的乱码问题。

完整迁移脚本

把以下代码保存为dedecms-to-typecho.php,配置好两边数据库信息,上传到Typecho网站根目录,浏览器访问执行:

<?php
/**
 * DedeCMS 到 Typecho 文章数据迁移工具
 */
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('max_execution_time', 3600);
ini_set('memory_limit', '512M');

$dedeConfig = [
    'host' => 'localhost',
    'user' => 'root',
    'pass' => '',
    'name' => 'dedecms',
    'prefix' => 'dede_'
];

$typechoConfig = [
    'host' => 'localhost',
    'user' => 'root',
    'pass' => '',
    'name' => 'typecho',
    'prefix' => 'typecho_'
];

try {
    $dedeDb = new PDO(
        "mysql:host={$dedeConfig['host']};dbname={$dedeConfig['name']};charset=utf8mb4",
        $dedeConfig['user'],
        $dedeConfig['pass'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false]
    );
    $typechoDb = new PDO(
        "mysql:host={$typechoConfig['host']};dbname={$typechoConfig['name']};charset=utf8mb4",
        $typechoConfig['user'],
        $typechoConfig['pass'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false]
    );
    echo "数据库连接成功\n<br>";
} catch (PDOException $e) {
    die("数据库连接失败: " . $e->getMessage() . "\n<br>");
}

// 获取DedeCMS栏目
echo "开始获取DedeCMS栏目\n<br>";
$dedeCateStmt = $dedeDb->query("SELECT id, typename FROM {$dedeConfig['prefix']}arctype");
$categoryMap = [];
while ($cate = $dedeCateStmt->fetch(PDO::FETCH_ASSOC)) {
    $categoryMap[$cate['id']] = $cate['typename'];
}
echo "成功获取 " . count($categoryMap) . " 个DedeCMS栏目\n<br>";

// 处理Typecho分类
$existingCategories = [];
$typechoCateStmt = $typechoDb->query("SELECT mid, name FROM {$typechoConfig['prefix']}metas WHERE type = 'category'");
while ($cate = $typechoCateStmt->fetch(PDO::FETCH_ASSOC)) {
    $existingCategories[$cate['name']] = $cate['mid'];
}

// 创建分类映射
$cateMigrationMap = [];
foreach ($categoryMap as $dedeCateId => $dedeCateName) {
    if (isset($existingCategories[$dedeCateName])) {
        $cateMigrationMap[$dedeCateId] = $existingCategories[$dedeCateName];
        echo "分类已存在复用: {$dedeCateName}\n<br>";
        continue;
    }
    $stmt = $typechoDb->prepare("INSERT INTO {$typechoConfig['prefix']}metas (name, slug, type, description, count, `order`) VALUES (:name, :slug, 'category', '', 0, 0)");
    $slug = preg_replace('/[^\w]+/', '-', strtolower($dedeCateName));
    $stmt->execute([':name' => $dedeCateName, ':slug' => $slug]);
    $cateMigrationMap[$dedeCateId] = $typechoDb->lastInsertId();
    echo "创建新分类: {$dedeCateName}\n<br>";
}

// 迁移文章
$pageSize = 100;
$offset = 0;
$totalMigrated = 0;
$duplicateSlugCount = 0;

do {
    $stmt = $dedeDb->prepare("SELECT a.id AS aid, a.title, a.senddate, a.typeid, a.arcrank, b.body FROM {$dedeConfig['prefix']}archives a LEFT JOIN {$dedeConfig['prefix']}addonarticle b ON a.id = b.aid WHERE a.channel = 1 LIMIT :pageSize OFFSET :offset");
    $stmt->bindValue(':pageSize', $pageSize, PDO::PARAM_INT);
    $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
    $stmt->execute();
    $articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $articleCount = count($articles);
    if ($articleCount == 0) break;

    foreach ($articles as $article) {
        $targetSlug = (string)$article['aid'];
        $checkStmt = $typechoDb->prepare("SELECT cid FROM {$typechoConfig['prefix']}contents WHERE slug = :slug");
        $checkStmt->execute([':slug' => $targetSlug]);
        if ($checkStmt->fetch()) {
            $duplicateSlugCount++;
            continue;
        }
        $status = $article['arcrank'] == 0 ? 'publish' : 'draft';
        $content = $article['body'] ?? '';
        $insertStmt = $typechoDb->prepare("INSERT INTO {$typechoConfig['prefix']}contents (title, slug, created, modified, text, authorId, status, type, commentsNum, parent, `order`) VALUES (:title, :slug, :created, :modified, :text, 1, :status, 'post', 0, 0, 0)");
        $insertStmt->execute([
            ':title' => $article['title'],
            ':slug' => $targetSlug,
            ':created' => $article['senddate'],
            ':modified' => $article['senddate'],
            ':text' => $content,
            ':status' => $status
        ]);
        $contentId = $typechoDb->lastInsertId();
        if (isset($cateMigrationMap[$article['typeid']])) {
            $relationStmt = $typechoDb->prepare("INSERT INTO {$typechoConfig['prefix']}relationships (cid, mid) VALUES (:cid, :mid)");
            $relationStmt->execute([':cid' => $contentId, ':mid' => $cateMigrationMap[$article['typeid']]]);
        }
        $totalMigrated++;
    }
    $offset += $pageSize;
} while ($articleCount == $pageSize);

echo "迁移完成 成功: {$totalMigrated} 跳过: {$duplicateSlugCount}\n<br>";
?>

这套代码我用过六次,最大规模8.7万篇文章,单次跑完约45分钟。注意几点:图片路径替换默认注释掉了,需要的时候取消注释;作者ID硬编码为1,多作者站点见后面FAQ的修改方法;keywords迁移需要在insertStmt后追加标签处理代码(见FAQ第3条)。

迁移后的关键配置

Nginx伪静态:在Typecho站点的nginx配置里加入以下规则:

location / {
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php$1 last;
    }
}

修改完执行nginx -t检查语法,再nginx -s reload。如果是宝塔面板,直接在网站设置-伪静态里选typecho模板即可。

固定链接格式:登录Typecho后台-设置-永久链接,选自定义链接,填{slug}.html。这样文章URL变成"域名/123.html",跟DedeCMS的"域名/123.html"完全一致(前提是DedeCMS用的是默认链接格式)。

如果DedeCMS用的是"分类/aid.html"格式,Typecho的自定义链接填"{category}/{slug}.html"对应。

SEO保稳的核心动作

4.1 301重定向规则的完整写法

大多数客户的DedeCMS都是默认链接格式(/分类slug/aid.html),迁移到Typecho后URL一致就不需要重定向。但有几种特殊情况必须做301:

情况一:DedeCMS的aid.html改成slug.html(slug用文章标题转拼音)。这时必须做aid到slug的全表映射重定向。在nginx里逐条写rewrite会爆炸,正确做法是用map指令:

map $request_uri $rewrite_target {
    /old/123.html /new/article-title-1.html;
    /old/124.html /new/article-title-2.html;
}
server {
    if ($rewrite_target) {
        return 301 $rewrite_target;
    }
}

map文件用脚本从数据库生成,几万条规则可以正常工作(map内部用hash实现,O(1)查找)。

情况二:DedeCMS的"category/aid.html"改成纯"/slug.html"。这时用正则即可:rewrite ^/category/(\d+)\.html$ /$1.html permanent;

情况三:tag页URL变化。DedeCMS的tag URL是tags.php?/abc/,Typecho是/tag/abc.html。规则:rewrite ^/tags\.php\?/(.+)/$ /tag/$1.html permanent;

sitemap.xml的提交与索引保稳

迁移完之后必须立即重新生成sitemap.xml并提交。Typecho装Sitemap插件,自动生成。提交渠道:Google Search Console的Sitemaps面板、百度搜索资源平台、Bing Webmaster Tools。建议同时提交。

百度有个特殊的"sitemap提交"额度,普通站点每天200条API推送限额。可以装BingIndexNow插件(Typecho生态有,能同时推送Bing和百度),新文章发布自动推送。

历史文章的索引保稳:Google Search Console的Coverage报告会显示索引状态。如果发现大量页面从Valid变成Excluded,说明robots.txt或meta robots有问题,要检查Typecho主题模板里的head输出。

内链与目录结构的SEO权重保留

DedeCMS的内链分布是网站权重的核心,迁移后必须保留:tag页面、分类页面、专题页面的URL结构一致;面包屑导航在Typecho主题里实现并加BreadcrumbList结构化数据;内链锚文本如果指向具体文章,URL不变就不用动;如果有专题(DedeCMS的special_id),Typecho里可以用独立分类或者自定义页面对应。

主题的SEO优化要点

选Typecho主题时优先考虑:H1只在文章页用一次(避免列表页也用H1);H2/H3层级清晰;图片自动lazy load;首屏不阻塞渲染;结构化数据完整(Article、BreadcrumbList、FAQPage、Person);Core Web Vitals三项达标。

市面上Typecho主题良莠不齐,我自己用的zhangwenbao-v2是定制开发的。如果想用现成主题,建议Joe、handsome这两个相对完善。装完后用Google Rich Results Test验证结构化数据,用PageSpeed Insights跑Core Web Vitals。

迁移后的注意事项与验证

数据完整性核对

迁移完成后必须做四项核对:文章总数对得上(DedeCMS的archives表count vs Typecho的contents表count)、分类数对得上、每个分类下的文章数对得上、随机抽30篇文章看内容是否完整(特别是HTML标签、图片路径、特殊字符)。

抽查SQL:SELECT title, LENGTH(text) FROM typecho_contents ORDER BY RAND() LIMIT 30; LENGTH显示字节数,如果有一批文章LENGTH小于500说明可能内容截断,要查dede_addonarticle表的body字段是否完整。

字符集陷阱

DedeCMS的旧版本(5.7之前)默认用GBK字符集,迁到Typecho的utf8mb4之前必须先转码。检查方法:mysql -u root -p -e "SELECT @@character_set_database FROM dedecms.dual"。如果显示gbk,必须先转utf8mb4:

mysqldump --default-character-set=gbk -u root -p dedecms > dede_gbk.sql
iconv -f gbk -t utf-8 dede_gbk.sql -o dede_utf8.sql
sed -i 's/CHARSET=gbk/CHARSET=utf8mb4/g' dede_utf8.sql
sed -i 's/SET NAMES gbk/SET NAMES utf8mb4/g' dede_utf8.sql
mysql --default-character-set=utf8mb4 -u root -p dedecms_new < dede_utf8.sql

转完之后用dedecms_new作为迁移源,避免乱码。

调试模式必须关闭

迁移脚本顶部开了error_reporting(E_ALL)和display_errors=1,迁移完成后必须修改为error_reporting(0)或直接删除脚本文件。否则任何后续访问这个URL会暴露服务器路径、数据库结构信息,是严重的安全风险。

保险做法:迁移完成后立即在网站根目录删除dedecms-to-typecho.php文件,或者用chmod 000禁止访问。

性能调优与缓存

Typecho默认没有缓存,2万篇文章规模下首页加载会有压力。装PageCache插件(或者用zhangwenbao主题自带的pagecache机制)能解决80%的性能问题。Nginx侧可以加fastcgi_cache做L1缓存:

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=TYPECHO:100m max_size=1g inactive=60m;
location ~ \.php$ {
    fastcgi_cache TYPECHO;
    fastcgi_cache_valid 200 30m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
}

这样的两级缓存(fastcgi_cache + Typecho内部cache)能让2核4G的服务器扛住每天10万次访问。

监测与异常告警

迁移后头两周必须密切监测:Google Search Console的Coverage报告每天看一次,重点关注Excluded里的"Crawled - currently not indexed"是否激增;百度站长平台的"抓取诊断"测试几个核心页面是否能正常抓取;Bing Webmaster Tools的Crawl Information看是否有大量404;服务器日志里grep "404"看是否有大量未配置的旧URL。

典型的迁移后2周流量曲线:迁移当天流量略降(DNS解析、CDN缓存切换)、迁移后2到5天流量回升到迁移前水平(搜索引擎更新索引)、迁移后2周流量超过迁移前(Typecho的Core Web Vitals优势开始生效)。如果迁移后一周流量没回升,立即排查nginx日志和Search Console报告。

实战中遇到的典型问题

标签数据丢失

原脚本只迁移文章和分类,标签(dede_taglist表)没动。补救方法:迁移完文章后单独跑一个标签迁移脚本,根据文章和标签的关联表dede_taglist+dede_tagindex插入到typecho_metas(type='tag')和typecho_relationships。这个补救脚本我下次再贴。

自定义字段未迁移

DedeCMS的"自定义字段"(addonarticle表的description/litpic等)原脚本没处理。如果你的内容用了大量自定义字段(典型场景:电商类站点的产品描述、价格、规格),必须修改脚本添加字段映射,对应到Typecho的typecho_fields表。

评论数据丢失

原脚本不迁移评论。如果评论数据重要,需要补一个评论迁移脚本,从dede_feedback映射到typecho_comments。注意字段对应:dede_feedback.dtime对应typecho_comments.created,dede_feedback.check对应typecho_comments.status(check=1转status='approved')。

文章作者归属错误

原脚本authorId硬编码为1。多作者站点需要建立作者映射数组并修改插入逻辑。我自己的实操:先建立DedeCMS作者ID到Typecho作者ID的映射表(写在脚本顶部),$authorMap=[1=>2, 3=>1, 5=>3]这样的格式,然后把insertStmt里的硬编码1改成$authorMap[$article['mid']] ?? 1。

图片防盗链失效

很多DedeCMS站点开了图片防盗链(在nginx里限制Referer),迁移到新域名后图片可能加载失败。解决方法:在Typecho的nginx配置里把图片防盗链规则的allowed referer改成新域名+旧域名(保留旧域名是为了过渡期)。

迁移之后的SEO持续优化

内容质量重做

从DedeCMS迁过来的老内容很多是十年前的,不符合当下E-E-A-T要求。建议挑Top 50访问量文章逐篇重写:补2000字以上的深度内容、加FAQ段、补结构化数据、新增配图。这一波内容质量重做做完,整站权重会有显著提升。

内链结构重构

用Screaming Frog或者Ahrefs Site Audit跑一次站点内链结构图,识别"孤岛页面"(没有内链指向的页面)。给孤岛页面手动加内链入口,让所有页面都能在3次点击内被爬虫触达。

结构化数据补全

Typecho主题如果默认不支持结构化数据,必须手动加。Article+BreadcrumbList+FAQPage是必备三件套,对应的JSON-LD代码加在主题的header.php或single.php里。补完之后用Google Rich Results Test逐页验证。

性能持续优化

Cloudflare Free Plan免费用、Typecho开pagecache、图片转WebP、Hero图加fetchpriority="high"、Google Fonts本地化或者用system font。这一套打下来Core Web Vitals三项全绿不难。

常见问题解答

迁移后原DedeCMS的URL如何301到Typecho?

如果Typecho固定链接选{slug}.html且slug=DedeCMS的aid,URL完全一致不需要重定向。如果URL结构变了,Nginx配置文件里加rewrite规则。Apache用.htaccess的Redirect 301指令。批量映射数百条规则用Nginx的map指令最高效。重定向后必须在Google Search Console提交sitemap.xml加速搜索引擎更新索引。

多作者站点怎么改作者ID硬编码?

先建立映射数组写在脚本顶部,比如authorMap=[1=2,3=1,5=3]这样DedeCMS作者ID到Typecho作者ID。找到insertStmt里的authorId硬编码1,改成authorMap[article的mid]??1。注意DedeCMS存作者的字段名要确认,通常是dede_archives的mid或writer,不同版本可能略有差异。修改后先测试1到2篇不同作者文章,确认归属正确再批量。

迁移后内部链接失效怎么批量修复?

两种方式:方法一在数据库直接跑UPDATE typecho_contents SET text=REPLACE(text, 旧域名, 新域名),注意先备份再执行;方法二在迁移脚本content变量后加str_replace替换。建议方式一更可控。修复完随机抽查10到20篇文章确认内链能跳转。如果内链是相对路径不带域名,迁移后通常不需要修改。

PHP版本8.2兼容这套脚本吗?

兼容但有两处可能的差异。一是strtolower传null的Deprecated警告,在tag=trim(tag)后加if empty(tag) continue过滤掉空标签。二是PDO第四参数必须是数组(脚本已正确设置)。最稳的做法是在脚本顶部加error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT)屏蔽废弃警告不影响功能。

怎么把DedeCMS的自定义字段也迁过去?

分两步。第一步在文章查询SQL里SELECT a.litpic和b.description这类字段;第二步在文章插入后用INSERT INTO typecho_fields cid name type str_value写入。Typecho原生支持自定义字段不需要装插件。映射示例:DedeCMS的litpic到Typecho的thumb字段、description到desc字段。注意字段类型用str_value存字符串、int_value存整数。

评论数据能不能迁过去?

能但需要补脚本。从dede_feedback表查WHERE check=1的已审核评论,映射到typecho_comments表。字段对应:cid是文章ID(必须先有文章再插评论)、author是评论者名字、mail是邮箱、url是网址、text是内容、created是时间戳(DedeCMS的dtime直接是Unix时间戳)、status是approved/spam/waiting。回复关系parent字段如果原数据有就保留没有就置0。

PDO MySQL扩展未启用怎么办?

Linux下用yum install php74-php-pdo php74-php-mysqlnd安装然后重启php-fpm或者apache。Windows IIS下打开php.ini找到分号开头的extension=pdo_mysql去掉分号保存重启IIS。验证方法是创建一个phpinfo页面看是否有PDO drivers的mysql项。常见坑:装了多个PHP版本没改对应版本的php.ini,可以用php -i grep php.ini确认当前加载的是哪个配置文件。

二级分类层级会不会混乱?

原脚本只迁一级分类。修改思路:处理Typecho分类时SELECT语句加parent字段;获取DedeCMS栏目时SELECT id typename reid(reid是父分类ID 0表示一级);创建分类时如果reid不等于0就把parent设为父分类在Typecho的mid,需要先迁移完所有一级分类再迁二级。这样二级分类会自动归属到父分类下层级与DedeCMS一致。

Typecho后台媒体管理看不到图片怎么办?

原因是Typecho媒体库只显示后台上传的图片,迁过来的图片没在typecho_attachments表登记。补救SQL:INSERT INTO typecho_attachments扫描typecho_contents.text里出现的img src路径,提取唯一路径插入到attachments表。不影响图片实际访问,只是后台看不到管理。如果图片量大不在乎后台管理可以忽略这一步。

DedeCMS的数据库和文件还要保留吗?

建议数据库保留3个月用于核对,文件删除或禁用访问。保留期间做三项安全处理。一是禁用DedeCMS网站访问,Nginx的location里return 403拒绝所有访问。二是删除敏感文件包括dede/login.php后台和install.php安装文件。三是把DedeCMS数据库用户权限从读写改成只读,即使被入侵也无法修改数据。3个月后确认Typecho无问题再彻底删除。

FAQPage + Article AI 引用友好版

TL;DR · 60–80 字摘要 · 适用 ChatGPT / Perplexity / Gemini / 文心 引用

完整DedeCMS到Typecho迁移方法:PHP批量脚本(已实测六次最大8.7万篇)、Nginx伪静态、301重定向map写法、字符集GBK转utf8mb4、SEO保稳监测,附二十四小时复盘清单。

关键实体 · Key Entities

  • DedeCMS批量处理
  • DedeCMS
  • Typecho
  • 数据迁移
  • 网站搬家
  • SEO保稳
  • Typecho教程

引用元数据 · Citation Metadata

title:       DedeCMS转Typecho迁移完整指南:批量脚本+SEO保稳47步+11类避坑
author:      张文保 (Paul Zhang) — PatPat SEO 经理
url:         https://zhangwenbao.com/dedecms-to-typecho.html
published:   2025-10-13
modified:    2026-05-16
source-type: First-hand expert commentary
language:    zh-CN
license:     CC BY-NC-SA 4.0 (要求保留原文链接与作者归属)
分享到
标签
版权声明

本文标题:《DedeCMS转Typecho迁移完整指南:批量脚本+SEO保稳47步+11类避坑》

本文链接:https://zhangwenbao.com/dedecms-to-typecho.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交