# 保哥笔记 — Typecho教程
> 本分片含 9 篇文章,按发布日期倒序。全部分片索引见 https://zhangwenbao.com/llms-full.md
**站点**:https://zhangwenbao.com/
**分类**:Typecho教程
**生成**:2026-06-04 23:09:29 CST
---
## DedeCMS怎么迁移到Typecho?批量脚本加SEO不掉量
- URL:https://zhangwenbao.com/dedecms-to-typecho.html
- 分类:Typecho教程
- 发布:2025-10-13 | 更新:2026-06-01
- 摘要:织梦官方四年没补漏洞还要商业授权,弃用是必然。本文给出从评估、备份、批量迁移脚本到SEO保稳的完整路径,包含字符集转码、多作者映射、评论迁移、二级分类等八个真实踩坑。
- 关键词:DedeCMS批量处理,DedeCMS,Typecho,数据迁移,网站搬家
> **TLDR**:摘要:织梦官方四年没补漏洞还要商业授权,弃用是必然,迁到Typecho是个稳妥选择。本文给从评估、备份、批量迁移脚本到SEO保稳的完整路径和迁移工具的完整代码,覆盖字符集转码、多作者映射、评论迁移、二级分类等八个真实踩坑,再讲迁移后的验证和SEO持续优化。
> 摘要:织梦官方四年没补漏洞还要商业授权,弃用是必然,迁到Typecho是个稳妥选择。本文给从评估、备份、批量迁移脚本到SEO保稳的完整路径和迁移工具的完整代码,覆盖字符集转码、多作者映射、评论迁移、二级分类等八个真实踩坑,再讲迁移后的验证和SEO持续优化。
保哥最近在给一个老客户排查网站异常,发现这个用织梦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注入 (https://zhangwenbao.com/dedecms-membership-center-pm-php-injection-vulnerability-repair-method.html)、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网站根目录,浏览器访问执行:
'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
";
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage() . "\n
");
}
// 获取DedeCMS栏目
echo "开始获取DedeCMS栏目\n
";
$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
";
// 处理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
";
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
";
}
// 迁移文章
$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
";
?>
这套代码我用过六次,最大规模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 (https://zhangwenbao.com/blog-faq-writing-seo-geo-guide.html)、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站点开了图片防盗链 (https://zhangwenbao.com/using-htaccess-to-set-up-wordpress-anti-stealing-link.html)(在nginx里限制Referer),迁移到新域名后图片可能加载失败。解决方法:在Typecho的nginx配置里把图片防盗链规则的allowed referer改成新域名+旧域名(保留旧域名是为了过渡期)。
## 迁移之后的SEO持续优化
## 内容质量重做
从DedeCMS迁过来的老内容很多是十年前的,不符合当下E-E-A-T (https://zhangwenbao.com/strengthen-authority-eeat-signals-ai-citations-2026.html)要求。建议挑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无问题再彻底删除。
## Typecho各类页面meta robots和canonical配置:5类页面差异
- URL:https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html
- 分类:Typecho教程
- 发布:2024-12-11 | 更新:2026-06-01
- 摘要:Typecho默认主题有分页稀释权重、搜索页被索引、归档页浪费爬虫预算三类问题。本文按首页、文章、分类、标签、搜索、归档等七种页面类型给出完整的meta robots与canonical PHP代码,并讲清末尾斜杠归一、Sitemap联动和摘要展示指令。
- 关键词:ECSHOP跳转,meta robots,canonical,noindex,Typecho SEO
> **TLDR**:摘要:Typecho默认主题有分页稀释权重、搜索页被索引、归档页浪费爬虫预算三类问题。本文先给核心规则速览和完整的header.php代码,按首页、文章、分类、标签、搜索、归档七种页面类型配meta robots与canonical,再讲archiveUrl末尾斜杠归一、Sitemap.xml联动和实施后的验证清单。
> 摘要:Typecho默认主题有分页稀释权重、搜索页被索引、归档页浪费爬虫预算三类问题。本文先给核心规则速览和完整的header.php代码,按首页、文章、分类、标签、搜索、归档七种页面类型配meta robots与canonical,再讲archiveUrl末尾斜杠归一、Sitemap.xml联动和实施后的验证清单。
Typecho 自带的主题对 SEO 信号的处理一直比较简单粗暴——首页、分类页、文章页、搜索页全都输出一份 follow,index 完事。这种偷懒在站点小、关键词竞争弱时无所谓;一旦站点上规模、需要做精细化技术 SEO,就会暴露出一堆问题:分类页第 2 页和第 1 页争权重、搜索页大量低质量 URL 被索引、归档页占用爬虫预算却几乎不出流量。本文针对 Typecho 各页面类型——首页 / 文章页 / 单页 / 分类页 / 标签页 / 搜索页 / 归档页——以及它们的分页变体,给出一套 meta robots (https://zhangwenbao.com/is-meta-robots-noindex-nofollow-needed-with-canonical.html) 与 canonical (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html) 的完整规则代码(基于 $this->getCurrentPage() 与 $this->is() 函数),可以直接粘贴进 header.php 立即生效,并配合 noindex (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html) 阈值、URL 末尾斜杠归一、HTTPS canonical、404 与 301 处理、Sitemap.xml 联动等周边工作把 Typecho 站点的技术 SEO 一次性做到位。
## 为什么 Typecho 默认的 SEO 配置不够用
## 分页页面的权重稀释
Typecho 默认主题对分类页第 2/3/4... 页输出和第 1 页同样的 index,follow——这意味着 Google 会把它们都索引,但它们的内容大部分和第 1 页重复(只是商品/文章列表不同段落)。结果是:
- 分类页主关键词的权重被分散到 N 个分页 URL。
- 用户搜某分类时 Google 可能展示第 3 页给他(用户跳出率高)。
- 站内重复内容评分被拉低。
正确做法:分页页面 noindex,follow——不索引但允许爬虫跟踪链接。
## 搜索页 URL 被索引的低质量问题
Typecho 自带的搜索功能 URL 形如 /?s=keyword。如果搜索页没设 noindex,Google 会把这些 URL 全部索引——尤其是当外链或站内链接指向某些搜索结果页时。结果:
- 低质量索引页面爆炸增长。
- 每个搜索 URL 内容质量不可控(取决于谁搜了什么)。
- 潜在的 SEO 垃圾内容指控。
正确做法:搜索页 noindex,nofollow(搜索结果不索引、其上的链接也不需要爬虫跟踪——主要 URL 已经在主导航和分类里了)。
## 归档页的价值低于成本
"2024 年 3 月归档"这种按月/年的归档页,对长尾关键词几乎没贡献,但占用爬虫预算。建议 noindex,follow——不索引归档页但让爬虫沿着归档页里的链接进入文章页。
## 标签页的两难
标签页(tag page)介于"高价值"和"低价值"之间:
- 如果你的标签使用规范、每个标签下有 5+ 篇文章——标签页是有价值的关键词聚合页,应当 index。
- 如果标签滥用、单标签只有 1-2 篇文章——标签页就是低质量内容农场,应该 noindex。
本文规则给的是"index,follow"——假设你的标签使用规范。如果不规范,先把标签清理一遍再考虑索引。
## 核心规则速览
## 七种页面类型的 meta robots 矩阵
页面类型 | 第 1 页 / 主页面 | 第 N 页 / 分页 |
首页 is('index') | index, follow | noindex, follow |
文章页 is('post') | index, follow | — |
单页 is('page') | index, follow | — |
分类页 is('category') | index, follow | noindex, follow |
标签页 is('tag') | index, follow | noindex, follow |
搜索页 is('search') | noindex, nofollow | noindex, nofollow |
归档页 is('archive') | noindex, follow | noindex, follow |
## 完整 max-snippet 配置
对允许索引的页面,加 max-snippet:-1, max-video-preview:-1, max-image-preview:large 让 Google 在 SERP 里显示完整摘要、完整视频预览、大图——这是 2019 年 Google 推出的指令,用于鼓励高质量内容站点更大的展示空间。具体含义:
- max-snippet:-1:摘要长度无限制(默认值受 Google 限制为 160 字符左右)。
- max-video-preview:-1:视频预览长度无限制(默认仅几秒)。
- max-image-preview:large:图片预览展示大图(默认 standard 较小尺寸)。
## 完整 header.php 代码
## 基于 getCurrentPage 的精细化规则
把以下代码粘贴进当前模板的 header.php 的