wordpress迁移到hexo的不完全填坑指南(2018)

为什么要换博客

从11年开始学php,利用免费tk域名和免费虚拟主机搭建了个wordpress博客,当时很兴奋,觉得自己太牛逼了。
然后到12年慢慢的开始学着抢域名,其中挑选了3个域名,分别是mallol.cn,wcing.com,texiaoyao.cn。我的原则是简单好记,这3个都符合要求。
买域名了 当然不能浪费。就把mallol.cn当作博客来写,就是目前的blog.mallol.cn
然后看上了阿里云,当时cn域名需要备案 才能用国内服务器,所以也备案了。
好像一切都走上正轨了。
当时也不断在想这3个域名应该做什么内容好,林林总总试了很多次,过程不表,结局是悲壮的。
就这个博客还活着。等于是见证了我的成长。

博客在14年换了个极简主题后,一直没改过风格样式。

15年nodejs开始火遍全球,好像是去年还是前年听说了hexo,全静态页面,极客风,简洁到非常,正是我的款。于是就跃跃欲试,谋划着改版,直到2018年3月5号才正式破土动工。

我的系统架构

服务器: 阿里云 ubuntu 16.04 64位
内存: 2G
CPU: 1核
hexo: 3.6.0
web服务器: nginx
nodejs: 8.9.4
npm: 5.6.0
版本控制: git

安装步骤

一, 安装nodejs npm

不要直接apt-get install安装,版本太老了。不兼容最新版的hexo(3.6.0),有很多问题。
最好是下载最新版源码进行编译

1
2
3
4
5
wget https://nodejs.org/dist/v8.9.4/node-v8.9.4.tar.gz
tar xvf node-v8.9.4.tar.gz
./configure
make
sudo make install

耐心等待,喝杯咖啡回来就装好了。
nodejs自带npm工具,无需另外安装。

二, 安装hexo

假设你的blog项目路径在/home/www/hexoblog/下面

1
2
3
4
sudo npm install -g hexo
hexo init blog
cd blog
npm install

三,从wordpress后台导出所有内容

从wordpress后台导出所有内容

四, 把该xml传到服务器hexoblog目录

1
scp  zouhongzhao.wordpress.2018-03-06.xml name@ip:/home/www/hexoblog/

五,迁移数据

需要安装hexo-migrator-wordpress插件

1
npm install --save hexo-migrator-wordpress

停住,别直接导入,会各种报错,我因为这个报错问题搞了很久,妈的,当时恨不得把hexo打一顿。
比如有如下报错:
YAMLException: can not read a block mapping entry; a multiline key may not be an implicit key at line 2

Template render error: Error: expected end of comment, got end of file

Template render error: ….,)
总之各种错误,一言难尽,搞得我怀疑人生。

你需要把xml的数据先过滤下。
也就是修改下hexo-migrator-wordpress的源码。
主要有3个地方:

1
2
3
1,把`{{`改成`{ {`
2, 把`<pre></pre>`这些代码标签改成```,也就是md的代码标签。我就是因为这个吃了大亏。
3, 把`<title>内容</title>`,改成`<title><![CDATA[$1]]></title>`

我是这么改的。
第一步:

1
perl -pi -e 's,<title>(.*)</title>,<title><![CDATA[$1]]></title>,' zouhongzhao.wordpress.2018-03-06.xml

第二步:
修改hexo-migrator-wordpress的index.js。
在node_modules/hexo-migrator-wordpress/index.js。
你可以直接替换成我的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
var xml2js = require('xml2js'),
async = require('async'),
tomd = require('to-markdown').toMarkdown,
request = require('request'),
file = require('fs');

var captialize = function(str){
return str[0].toUpperCase() + str.substring(1);
};
function replaceTwoBrace(str){
str = str.replace(/{{/g, '{ {');
return str;
};
function replaceHTMLEntity(str){
str = str.replace(/amp;/g, '');
str = str.replace(/&lt;/g, '<');
str = str.replace(/&gt;/g, '>');
str = str.replace(/&quot;/g, '"');
str = str.replace(/&#92;/g, '\\');
str = str.replace(/&#48;/g, '0');
return str;
};
function replaceCodeTag(str){
str = str.replace(/(<pre class=).*?>/g, '<pre>');
str = str.replace(/\<pre\>/gi, '```\r\n');
str = str.replace(/\<\/pre\>/gi, '```');
//str = str.replace(/<pre>(.*)<\/pre>/ig, '```$1```');
//console.log(str);
// str = str.replace(/\[python\]/gi, '```');
// str = str.replace(/\[\/python\]/gi, '```');
// str = str.replace(/\[java\]/gi, '```');
// str = str.replace(/\[\/java\]/gi, '```');
// str = str.replace(/\[php\]/gi, '```');
// str = str.replace(/\[\/php\]/gi, '```');
// str = str.replace(/\[c\]/gi, '```');
// str = str.replace(/\[\/c\]/gi, '```');
return str;
};
hexo.extend.migrator.register('wordpress', function(args, callback){
var source = args._.shift();

if (!source){
var help = [
'Usage: hexo migrate wordpress <source>',
'',
'For more help, you can check the docs: http://hexo.io/docs/migration.html'
];

console.log(help.join('\n'));
return callback();
}

var log = hexo.log,
post = hexo.post;

log.i('Analyzing %s...', source);

async.waterfall([
function(next){
// URL regular expression from: http://blog.mattheworiordan.com/post/13174566389/url-regular-expression-for-links-with-or-without-the
if (source.match(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[.\!\/\\w]*))?)/)){
request(source, function(err, res, body){
if (err) throw err;
if (res.statusCode == 200) next(null, body);
});
} else {
file.readFile(source, next);
}
},
function(content, next){
xml2js.parseString(content, next);
},
function(xml, next){
var count = 0;

async.each(xml.rss.channel[0].item, function(item, next){
if (!item['wp:post_type']){
return next();
}
//console.log(item.title[0]);
var title = item.title[0],
id = item['wp:post_id'][0],
date = item['wp:post_date'][0],
slug = item['wp:post_name'][0],
content = item['content:encoded'][0],
comment = item['wp:comment_status'][0],
status = item['wp:status'][0],
type = item['wp:post_type'][0],
categories = [],
tags = [];

if (!title && !slug) return next();
if (type !== 'post' && type !== 'page') return next();
if (typeof content !== 'string') content = '';
content = replaceTwoBrace(content);
content = replaceHTMLEntity(content);
content = replaceCodeTag(content);
content = tomd(content).replace(/\r\n/g, '\n');
count++;

if (item.category){
item.category.forEach(function(category, next){
var name = category._;

switch (category.$.domain){
case 'category':
categories.push(name);
break;

case 'post_tag':
tags.push(name);
break;
}
});
}

var data = {
title: title || slug,
id: +id,
date: date,
content: content,
layout: status === 'draft' ? 'draft' : 'post',
};

if (type === 'page') data.layout = 'page';
if (slug) data.slug = slug.toString();
if (comment === 'closed') data.comment = false;
if (categories.length && type === 'post') data.categories = categories;
if (tags.length && type === 'post') data.tags = tags;
log.i('%s found: %s', captialize(type), title);
data.title = data.title.toString();
data.date = data.date.toString();
//console.log(data.slug);
//console.log(data.date);
post.create(data, next);
}, function(err){
if (err) return next(err);

log.i('%d posts migrated.', count);
});
}
], callback);
});

最后再导入wp的数据。

1
2
cd blog
hexo migrate wordpress ../zouhongzhao.wordpress.2018-03-06.xml

耐心等待,不报错的话 就是大吉大利。

六,生成静态文件

1
hexo clean & hexo generate —debug

加debug是为了看调试信息,看命令是否在工作。不然一等十几分钟终端没任务提示,还以为系统卡死了。

如果没报错的话,那就是万幸。

友情提醒下:
这个-debug的输出信息并不能准确的告诉你是哪个文件出错了。我就被坑了,以为是hexo核心文件的问题损坏了,重装了几次。
其实不是,多半是post文件有问题。
打开 node_modules/hexo/lib/extend/tag.js
搜索 env.renderString(str, options, (err, result)
在里面加上console.log(str);

1
2
3
4
5
6
console.log(str);
env.renderString(str, options, (err, result) => {
if (err) {
console.log(str);
return reject(err);
}

这样的信息才是最准确的。
你根据这个str的内容 搜索关键字 找到post文件 再检查 就知道了。

七,安装next主题


https://github.com/ahonn/hexo-theme-even

过程不表,很简单。
完事后。打开项目的_config.yml文件,把theme改成next就行。

hexo g下就ok了。

主题的使用说明。见http://theme-next.iissnan.com/
非常全面,该有的都有。

八,各种插件

http://theme-next.iissnan.com/
我装的有

  • 评论系统: 来必力
  • 搜索: Algolia
  • git自动提交: npm install hexo-deployer-git --save
  • 七牛: https://github.com/gyk001/hexo-qiniu-sync
  • cdn: https://github.com/zqjimlove/hexo-cdnify (将本地的js/css/images的url加入http://cdn.mallol.cn前缀。

九,nginx配置

生成的静态文件一般放在public下,
我的是/home/www/hexoblog/blog/public
直接在nginx里指定改目录即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name blog.mallol.cn;
root /home/www/hexoblog/blog/public;
index index.html index.htm default.html default.htm;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 12h;
}
}

十,git配置

我文章很多,有400多篇。在服务器里直接hexo generate的话,要等20分钟,太尼玛慢了,搞得服务器很卡。没办法,我只好把代码下载到本地电脑上。
在本地电脑里hexo generate后,把最新生成的public文件push到服务器。

所以我在ubuntu服务器里配置了git。
1,创建git用户,在/home/git里mkdir blog.git

1
git init && git config --bool core.bare true

2,在服务器项目路径下

1
2
3
4
cd /home/www/hexoblog/blog/public
git init && git add . && git commit -a
git remote add origin /home/git/blog.git
git push origin master

3,本地电脑里也安装git,但是不需要git init这些,因为hexo已经帮你做好了。
hexo deploy这个命令就是push到服务器的
所以只需要在项目_config.yml里定义。找到deploy

1
2
3
4
deploy:
type: git
repo: git@ip:/home/git/blog.git
branch: master

这样就行了。
比如,在本地电脑的blog目录下执行hexo d
会提示你输入git密码。
hexo-deploy

hexo-deploy

这样就成功push到服务器了。

提示下:你们可能会跟我显示不一样,我装了七牛,以及设置了git hooks。
git hooks就是当push到git服务器后,git服务器会自动更新/home/www/hexoblog/blog/public的内容。就不需要我手动登陆服务器再pull了。

十一,一些常见的错误

WARN No layout: index.html
这个是没有在_config.yml定义主题,或者说themes下不存在_config.yml里的主题

title [object Object]
这个是hexo的文件有损坏了,需要重新init blog,再migrate和generate

好了,核心的东西就这些了。这些基本上就够你折腾了。

十二,心得体会

hexo目前最大的缺点就是hexo generate太慢太慢了,我400篇文章,耗时20分钟才搞完。
可能是我开启了category和tags的原因。

优点也很明显,极客风,自由配置,全命令行操作,简单粗暴,逼格高。
本地sublime text写文章比在网站后台写文章要好太多了,在线写的话 文章太长 经常会卡死。

坚持原创技术分享,您的支持将鼓励我继续创作!