xdays

Pelican和Github构建静态博客

缘起

最近因为要换工作了,时间比较空闲,所以打算好好整理下自己的博客。想来博客写的越来越少也挺惭愧,好多东西都只停留在笔记的草稿阶段,没有写成博客,后续慢慢整理出来。回到正题,我开博客伊始一直用wordpress(下文简称WP),有点自然不必多说,成熟稳定,功能全面,主题丰富;但是我最近渐渐在思考我真的需要它么,我的日常操作不过是当我的笔记草稿足以成型为一篇博客,我把它粘贴到WP的编辑框,选择下分类,打上标签,点击发布,仅此而已;为此还安装插件让WP支持直接在编辑器里贴markdown;所以我需要的只不过是能够渲染markdown,生成静态html即可,不需要php,也不需要数据库;此外,博客自动发布也是我需要的一个功能。

计划

首先,选择静态博客生成器。目前jekyll的风头最大,但我没有选择他有两个原因:一是学习成本比较高,我只是想用你生成html你却让我学习那么多东西,不值得;二是我是Python党,我希望我用的工具能提升我的Python技能,嗯,这个也很重要。所以我选择用Pelican,它足够简单,拿到就可以使用。

然后,迁移。基本所有的静态博客项目都提供了导入的功能,尤其从WP这样如此流行的项目,但是pelican-import这个工具在字符处理有一些坑,这个后边会详细提到。

再次,版本。既然所有的东西都是静态文本文件,那么自然而然想到可以用Git来管理所有mardown文本,托管在Github。

最后,自动发布。其实自动发布是个可有可无的功能,自己封装个脚本在写好markdown之后运行下脚本即可,成本和在WP上点击下发布相当,但是既然已经用上Github那何不好好用用Github的Webhook呢,这样就可以在新博客提交到Github时触发一个动作,剩下的就是响应这个动作来做博客构建了。博客构建是有逻辑的,而我不想为这一个需求再引入其他php或者python应用,考虑到静态博客唯一需要的就是一个Web服务器,我决定用Ningx+Lua的模式来处理这个Webhook。

至此,所有需求都有了恰当的解决办法。

实施

pelican

安装

pip install pelican markdown

配置

pelican-quickstart

使用

pelican的配置文件就是一个python代码文件,一般在博客根目录下的pelicanconf.py,主要定义一些博客本身的元信息,具体配置项可参考这里。content目录为markdown文件存放目录,每篇博客一个文件,在每篇文件得开头写一些meta信息,指定标题,作者,分类,tag和slug等信息。

修改pelicanconf.py,我的配置内容如下:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- # 
from __future__ import unicode_literals

# Misc 
AUTHOR = u'xdays' 
SITENAME = u'xdays' 
SITEURL = 'http://xdays.me' 
KEYWORD = '架构,运维,开发, 生活随想' 
PATH = 'content' 
STATIC_PATHS = ['wp-content'] 

# Time 
TIMEZONE = 'Asia/Shanghai' 
DEFAULT_LANG = u'zh' 

# Feed 
FEED_ALL_ATOM = None 
CATEGORY_FEED_ATOM = None 
TRANSLATION_FEED_ATOM = None 

# Menu 
MENUITEMS = (('首页', SITEURL),) 
DISPLAY_PAGES_ON_MENU = True 
DISPLAY_CATEGORIES_ON_MENU = False 

# Pagination 
DEFAULT_PAGINATION = 20 

# Output 
DELETE_OUTPUT_DIRECTORY = True 

# Disqus 
DISQUS_SITENAME = "xdays" 

# Github 
GITHUB_USER = 'xdays' 
GITHUB_REPO_COUNT = 5

最后生成博客:

pelican -s pelicanconf.py -t theme content

注意:-t可以指定主题路径

pelican-import

首先要导出wordpress的文章为xml文件,需要安装一个叫wordpress-importer的插件。

安装pelican-import的依赖:

apt-get install python-lxml pandoc
pip install BeautifulSoup4

导出markdown文件:

pelican-import --wpfile wordpress.xml -m markdown -o content

下边开始说坑,在每个markdown文件有个slug的meta标记,这个标记是生成的html的文件名,但是由于pelican-import对字符集处理的不是太好,所以需要自己手动将slug进行一次unquote,然后用unquote之后的字符串来命名文件,废话少说,上代码:

 #!/usr/bin/env python # -*- coding: utf-8 -*- from urllib import unquote import os import sys top = sys.argv[1] out = sys.argv[2] flist = sum([[os.path.join(base,file) for file in files] for base,dirs,files in os.walk(top)],[]) os.mkdir(out) for i in flist: dirname = os.path.dirname(i) with open(i) as f: s = f.readlines() for l in s: if l.startswith('Slug'): index = s.index(l) p = l.strip().split()filename = unquote(p[-1]) p[-1] = filename + '\n' s[index]=' '.join(p) with open('%s/%s.md'%(out, filename), 'w') as g: g.write(''.join(s)) break 

这段代码接受两个参数:第一个是导出的markdown目录,第二个是处理后的markdown文件存放目录。

Github

将整个博客目录交给Git管理:

git init 
git add . 
git commit -m 'first owesome commit' 
git remote add origin git@github.com:xdays/xdays.me.git 
git push -u origin master

然后配置webhook,具体参考Github文档

Nginx+Lua

安装

安装过程涉及的环节比较多,也可以直接使用openresty,下面脚本详细说明了安装过程:

apt-get install libpcre3-dev zlib1g-dev build-essential

cd ~ 
wget http://nginx.org/download/nginx-1.7.4.tar.gz 
tar xzf nginx-1.7.4.tar.gz 
wget http://luajit.org/download/LuaJIT-2.0.3.tar.gz 
tar xzf LuaJIT-2.0.3.tar.gz 
wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.9.10.tar.gz 
mv v0.9.10.tar.gz lua-nginx-module-0.9.10.tar.gz 
tar xzf lua-nginx-module-0.9.10.tar.gz 

cd ~/LuaJIT-2.0.3 
make install PREFIX=/usr/local/xengine/luajit 
cd ~/nginx-1.7.4 
./configure --with-ld-opt="-Wl,-rpath,/usr/local/xengine/luajit/lib" --with-http_stub_status_module --add-module=/root/lua-nginx-module-0.9.10/ --prefix=/usr/local/xengine/nginx 
make -j2 
make install

配置

在博客的的server配置里添加如下配置:

    location /example-url {
        content_by_lua_file /path/to/genblog.lua;
    }

再上lua代码:

os.execute('export LANG=zh_CN.UTF-8 && cd /blog/path && pelican -s pelicanconf.py content/ -t theme/')
ngx.header.content_type = "text/html"
ngx.print('success\n')

return ngx.exit(ngx.HTTP_OK)

使用

对博客做一些修改,然后请求如下url,看效果:

curl localhost/example-url

返回success表示博客构建成功

联动

最后就是给Github配置上上一小节配置的webhook playload url接口即可。

Comments