博客从 Ghost 迁移到 Hexo

这两天我的博客不能访问了,因为 Azure 服务器这个月到期了,服务器被彻底回收了。我立刻买了一个阿里云的服务器,安装好环境,配置好我钟爱的 Ghost 博客。因为之前的博客数据都备份的很好,很快恢复了全部博文。然后把我的域名修改一下解析,访问 www.race604.com,完美。正当我舒一口气的时候,网页突然变成了这样:

aliyun

WTF,这是什么鬼,竟然要!!备!!案!!,因为之前的服务器实在香港,所以一直不知道还有这么回事。我按照网上的流程,赶紧走备案流程,填写资料、上传身份证、打印核验单、签字、拍照片照相上传,提交。我能做的就是等了。

同时,我向群里的大神们求助,了解到,如果使用阿里云的服务器,使用 80 端口搭建网站,必需要备案,而且备案流程需要 20 天左右,今天接到阿里云客服的电话,也确认需要 18 到 20 个工作日。我当时的表情是这样的:

WTF

群里面又好几个朋友主动 Share 给我主机,非常感激。还有朋友建议使用 Hexo 加 Github 或者 GitCafe 的 Pages 服务来搭建静态博客。在接下来差不多一个月的备案审核的等待中,我准备用这种方案来支撑一下。

吐槽了这么多,稍微平复了一下我焦躁的心情,下面说一下具体博客迁移的过程,有一些小坑,希望看了本文的朋友能避免。

1. Hexo 安装

Hexo 是基于 Node.js 的,那就非常简单了,就像项目主页上所展示的,几条命令就搞定了。当然前提是你要安装好 Node.js 和 npm。

$ npm install hexo-cli -g
$ hexo init blog
$ cd blog
$ npm install
$ hexo server

2. Hexo 写文章

Hexo 写文章,首先在你的 Hexo blog 根目录,使用如下命令:

$ hexo new <title>

这会在生成 source/_posts/<title>.md Markdown 文件,这里的 <title> 就是标题,也是文章的 URL。文章就在这个 .md 文件写就可以了,但是需要注意一点,看一下这个生成的文件:

title: hello world  
date: 2015-08-04 21:19:56  
tags:  
---
...

可见,在文件的头部,用 YAML 格式编写一些文章的基本信息。每个字段的含义就不解释了,特别需要注意的是,如果 title 字段有特殊字符,可能后面生成回出错,所以最好加上双引号("")。具体还有哪些字段可以设置,可以参考这里。 写好文章以后,使用如下命令,即可生成博客了:

$ hexo g

Hexo 所有命令,可以参考这里。具体的部署,放到后面说。

3. Ghost 博客导出

重前面我们可以看到,只要把文章导出成 .md 文件,放到 source/_posts/ 目录下即可。

Ghost 博客后台有导出工具,导出的是一个 JSON 文件,包含了很详细的博文信息。因为文章较多,如果直接解析这 JSON 文件还有点费劲。因为 Ghost 后台是数据库存储,直接从数据库中导出更方便。
分析一下 Ghost 的数据库,发现 Schema 非常简单直接:文章存储在 posts 表中,特别是,表中 markdown 列,保存了文章的 Markdown 原文件;标签在 tags 表中;文章的标签,在一个关联表 posts_tags 表中。我们需要的数据有:标题、发布日期、文章标签、slug(文章的 URL)、正文等。

因为我的 Ghost 用的是 MySQL,我打算用 Python 直接从 MySQL 数据库中把文章读出来,Python 脚本主要的代码如下:

con = mdb.connect('localhost', user, password, dbname)  
cur = con.cursor()  
cnt = cur.execute('select id,slug,title,markdown,published_at from posts')  
print 'Total %s posts' % cnt  
posts = cur.fetchmany(cnt)  
for row in posts:  
    print "post: %s" % row[1]

    output = open(outDir + "/" + row[1]+'.md', 'w')
    output.write("title: \"%s\"\n" % row[2])
    output.write("date: %s\n" % row[4])
    output.write("tags: [")
    tagcnt = cur.execute('select name from posts_tags join tags on posts_tags.tag_id = tags.id where posts_tags.post_id = %s' % row[0])
    for i in range(tagcnt):
        if i > 0 :
            output.write(' ,')
        tag = cur.fetchone()
        output.write("%s" % tag)
    output.write("]\n")
    output.write("---\n")

    output.write(row[3])
    output.close()

print 'export finish, OK!'  

完整的脚本在 Github 上 GhostExport。执行本脚本,会按照 Hexo 的文档格式,把所有的文章到导出指定的目录中。

另外,此脚本依赖于 mysql-python,可以通过如下命令安装:

$ sudo apt-get install python-setuptools
$ sudo apt-get install libmysqld-dev
$ sudo apt-get install libmysqlclient-dev
$ sudo apt-get install python-dev
$ sudo easy_install mysql-python

把所有导出的 .md 文件放到 source/_posts/ 目录下,执行如下命令:

$ hexo g
$ hexo server

然后在浏览器中打开:http://0.0.0.0:4000/, 就可以看到你的博客效果了。

4. 部署

Hexo 可以部署在 GitHubGitCafe。因为是国内访问,我先考虑部署在国内的 GitCafe 上,这样访问速度快一些。你要注册一下你 GitCafe 账号,上传你的 ssh 公钥。具体步骤流水账如下:

  1. GitCafe 注册账号;
  2. 这里添加你的 ssh 公钥,这是为了让你在本机上不用输入密码上传代码,具体步骤参考这里。也可以专门为 GitCafe 单独设置一个 ssh 秘钥,参考这篇的秘钥配置部分(其他部分最好不要看了,因为我按照他描述的步骤,走了很多弯路);
  3. 在 GitCafe 上创建一个空的公开的项目,项目名必须和你的用户名完全一致,其他就不用管了;
  4. 配置 Hexo 部署,修改 Hexo 根目录的 _config.xml 文件,如下:
deploy:  
  type: git
  repository: git@gitcafe.com:<username>/<username>.git
  branch: gitcafe-pages
其中,`type` 是 `git`,有些博客写成 `github`,是部署不成功的。 `repository` 替换成你自己刚创建的 repo 地址,例如我的就是:`git://gitcafe.com/race604/race604.git`。

5. 部署,执行如下命令:

hexo d  

然后访问 http://<username>.gitcafe.io 就能看到你的博客。例如我的是:http://race604.gitcafe.io

到这里基本使用就没有问题了。如果需要更多好玩的,请继续往下看:

5. 添加自定义域名

如果你有自己的独立域名,在 GitCafe 上前面创建的项目,进入“项目设置”,选择“Pages 服务”,在这添加你的域名。

设置你的域名解释,添加一条 "CNAME" 解析到 <username>.gitcafe.io,例如,我就添把 www.race604.com 添加 CNAME 解析到 race604.gitcafe.io,直接访问 http://www.race604.com/ 即可。

6. 主题

自己的博客怎么能没有各种酷酷的主题,这里是官方的主题页面。这里推荐一个很漂亮的主题 Yilia,也是我用的主题。安装非常方便,官方文档说的很清楚。

7. 同时部署 Github 和 GitCafe

在群里,有大神建议同事部署 Github 和 GitCafe,配置 DNS,国外访问 GitHub,国内就访问 GitCafe。具体教程有: 1. 在github和gitcafe上同时部署hexo博客
2. DNS 设置国内国外分别访问参考这篇后半部分。

8. 添加百度统计

网站怎么能没有访问统计,Hexo 添加百度统计也非常容易。因为我用的是 Yilia 主题,这篇文章详细介绍了 Yilia 主题怎么添加百度统计。

9. 添加搜索

今天刚好干货集中营提到了,使用微搜索可以轻松添加站内搜索。我试了一下,确实非常方便,我也给我的博客添加上了,欢迎搜索。具体添加方法,可以模仿前面的添加百度统计一节。

10. 兼容 Ghost 问题

  1. 评论
    Yilia 主题用的多说评论,我之前的 Ghost 也是多说。但是因为里面的评论文章 Key 配置的不一样,所以不能自动迁移过来,确实有点遗憾。
  2. 文章 URL
    _config.xml 中,文章的 URL 默认配置是:
permalink: :year/:month/:day/:title/  

为了和以前的 Ghost 文章 URL 一致,修改如下:

permalink: :title/  

另外,因为 Ghost 的 Tags 文章列表,路径是 /tag/tagname,而 Hexo 默认是 /tags/tagname,这个也可以为与 Ghost 一致,修改 _config.xml:把 tag_dir: tags 改为 tag_dir: tag 即可。但是 Hexo 是大小写敏感的,所以还是不能完全兼容 Ghost 的所有的 URL。 3. RSS Feed
Hexo 默认没有输出 RSS Feed,可以通过安装 hexo-generator-feed 插件输出 RSS。但是输出的 RSS 路径有点不一样,以前订阅博客的朋友,可能就收不到更新了,还有我的自动邮件列表也不工作了。

总结

现在我的博客迁移已经完成了,写了这么多,总结一下:

  1. 选择国内的 VPS 需要备案,备案时间最少 18 到 20 个工作日;
  2. 做好数据备份;
  3. Blog 平台切换有很多代价,包括时间和兼容性。在迁移的时候,需要全面评估。

Read more

Android 上的低功耗蓝牙实践

这是我在 Droidcon Beijing 2016 和 GDG Devfest 2016 上做的分享,以下是正文: Slide 01 我今天分享的主题是 Android 上低功耗蓝牙的实践。这个主题比较小众。我在过去的一年多的时间里,主要是在做低功耗蓝牙相关的开发。接触过程中发现,BLE 的开发和通常的 Android APP 的开发有点不一样,这里需要访问硬件资源,而且涉及到一些协议相关的内容,而且这方面的资料也比较少。今天我从 Android 开发者的角度,来分享一下低功耗蓝牙开发实践。 Slide 02 今天分享的内容,主要包含如下几个部分:首先对蓝牙和低功耗蓝牙做一个简单的介绍;然后介绍 Android 上对低功耗蓝牙的支持;再介绍一下在 Android 平台上可以开发哪些低功耗蓝牙应用;然后是,开发过程中,可以帮助我们调试的工具;最后,总结一下所谓的 “最佳实践”,低功耗蓝牙开发的一些小经验。 Slide

By Race604

React Native 触摸事件处理详解

触控是移动设备的核心功能,也移动应用交互的基础,Android 和 iOS 各自都有完善的触摸事件处理机制。React Native(以下简称 RN)提供了一套统一的处理方式,能够方便的处理界面中组件的触摸事件、用户手势等。本文尝试介绍 RN 中触摸事件处理。 1. RN 基本触摸组件 RN 的组件除了 Text,其他组件默认是不支持点击事件,也不能响应基本触摸事件,所以 RN 中提供了几个直接处理响应事件的组件,基本上能够满大部分的点击处理需求TouchableHighlight, TouchableNativeFeedback, TouchableOpacity 和 TouchableWithoutFeedback。因为这几个组件的功能和使用方法基本类似,只是 Touch 的反馈效果不一样,所以一般我们用 Touchable** 代替。Touchable** 有如下几个回调方法: * onPressIn:点击开始; * onPressOut:点击结束或者离开; * onPress:单击事件回调; * onLongPress:长按事件回调。 它们的基本使用方法如下,

By Race604

React Native 中 ScrollView 性能探究

1 基本使用 ScrollView 是 React Native(后面简称:RN) 中最常见的组件之一。理解 ScrollView 的原理,有利于写出高性能的 RN 应用。 ScrollView 的基本使用也非常简单,如下: <ScrollView> <Child1 /> <Child2 /> ... </ScrollView> 它和 View 组件一样,可以包含一个或者多个子组件。对子组件的布局可以是垂直或者水平的,通过属性 horizontal=true/false 来控制。甚至还默认支持“下拉”刷新操作。另外还有一个特别赞的特性,超出屏幕的 View 会自动被移除,从而节省资源和提高绘制效率。我们来看如下一个例子: class

By Race604

30 天入门 Android 开发, Google 与你一起圆梦

经常会有朋友让我推荐 Android 开发入门的教程或者视频,我一直是推荐看官方的教程。大部分人或者觉得比较迷茫,或者觉得坚持不下去。这次推荐这个《30 天入门 Android 开发》是 Google 亲自发起的免费教学,以学习小组方式,大家可以一起学习和交流。一个好的开始,是成功的一半。让 Google 工程师带领你一起进入多彩的 Android 开发大门。点击这里 报名。 Android 设备已经随处可见,你想尝试一下在 Android 设备上的开发和创新吗?快来跟随 Google 的步伐,一起学习 Android 入门课吧! Google Study Jams 活动介绍 Study Jams 是一个学习 Google 在线课程的活动。该活动由学员自主发起课程学习小组,带领小组成员入门 Android 开发,最终将

By Race604