Tian Jiale's Blog

使用 Hexo 之后原有博客怎么办?

想法与思路

在一月底二月初写了一份博客代码,然后在两天前接触了 Hexo 这个静态博客生成器,悲剧地发现还是这个简单快捷。转为 Hexo 之后原博客代码要想不荒废那不是得每更一篇文就要去博客后台提交文章?而且有的文章小毛病一大堆可能要三天两头地修改,就这繁杂的工作能把我折腾地放弃写博客。

从一贯的删繁就简的思路来看,用 python 这种简单的语言来干这种事情那是最好的了。

python 同步数据库内容

知识储备

语言要求:

  • MySQL
  • python

用到的 python 模块

原数据库格式

create table usertb(
  id int primary key auto_increment,
  username varchar(20) unique not null,
  pass_word varchar(40) not null,
  email varchar(50),
  portrait varchar(200)
);
create table articletb(
  id int primary key auto_increment,
  title varchar(100) not null,
  img_url varchar(200) default "https://static.aecra.cn/aecra.png" not null,
  content text not null,
  publish_time timestamp not null default "2021-01-01 00:00:00",
  update_time timestamp not null default "2021-01-01 00:00:00",
  hided int default 0 not null,
  toped int default 0 not null,
  clicks int default 0,
  userid int default 1 not null,
  foreign key(userid) references usertb(id)
);
create table tagstb(
  id int primary key auto_increment,
  tagname varchar(15) not null
);
create table tagmaptb(
  id int primary key auto_increment,
  tagid int,
  articleid int,
  foreign key(tagid) references tagstb(id),
  foreign key(articleid) references articletb(id),
  unique(tagid,articleid)
);

导入 python 模块

import frontmatter
import pymysql
import os

初始化设置

# config
post_folder = './hexo/source/_posts/'
database = {
    'host': '',
    'user': '',
    'passwd': '',
    'db': ''
}

读取文章内容

# 读取所有的文章的内容
print("读取文章内容......")
posts = os.listdir(post_folder)

article_data = []

for post in posts:
    f = open(post_folder + post, encoding='utf-8-sig')
    item = frontmatter.loads(f.read())
    article = {
        'title': item['title'],
        'date': item['date'],
        'tags': item['tags'],
        'cover': item['cover'],
        'content': item.content
    }
    article_data.append(article)
article_data = sorted(article_data, key=lambda article: article['date'])
print("已读取文章内容")

连接数据库,进行数据库操作

# 连接数据库,进行数据库操作
print('连接数据库......')
conn = pymysql.connect(
    host=database['host'], user=database['user'], passwd=database['passwd'], db=database['db'], charset='utf8')
cursor = conn.cursor()
print('已连接数据库')

删除原有文章数据

# 删除原有文章数据
print('清空数据库......')
cursor.execute('truncate table tagmaptb')
cursor.execute('truncate table tagstb')
cursor.execute('truncate table articletb')
print('已清空数据库')

向数据库中添加数据

# 向数据库中添加数据
print('正在向数据库中添加文章......')
i = 0
for article in article_data:
    i = i + 1
    # 添加文章
    sql = ('INSERT INTO articletb '
           '(title,img_url,content,publish_time,update_time,userid) '
           'VALUES(%s,%s,%s,%s,%s,1)')
    cursor.execute(sql, [article['title'], article['cover'],
                         article['content'], article['date'], article['date']])
    # 获取文章id
    article_id = cursor.lastrowid
    # 建立文章和标签的链接
    for tag in article['tags']:
        # 标签不存在就插入标签
        res = cursor.execute('select * from tagstb where tagname=%s', [tag])
        if res == 0:
            cursor.execute('insert into tagstb(tagname) values(%s)', [tag])
        # 获取标签id
        cursor.execute('select * from tagstb where tagname=%s', [tag])
        tag_id = cursor.fetchone()[0]
        # 向映射表中插入数据
        cursor.execute('insert into tagmaptb(tagid,articleid) values(%s,%s)', [
                       tag_id, article_id])
    print('(', i, '/', len(article_data), ') 已添加:', article['title'])
print('添加完成')

关闭数据库

# 关闭数据库
print('关闭数据库......')
cursor.close()
conn.close()
print('已关闭数据库')

遇到的问题

python-frontmatter 可以看到 frontmatter 是支持 frontmatter.load 的,但是在我应用的过程中发现有一个文件无论怎样更改都无法让 frontmatter 正常工作,而在打印 content 之后发现 front matter 的内容在 content 中,而且在这之前有一个乱码的字符,于是去到 GitHub 上 frontmatter 的 issue 中寻找答案。

issue 中我们可以发现是编码问题,于是乎,只能通过设置编码为 utf-8-sig 来解决问题。

sorted() 函数不改变原有的数组,需要写成 o = sorted(o) 的形式。

缺点

因为代码的复杂度问题,没有对文章地址,同时也就是 id 做永久性处理,在这样的处理方案下,如若某一天有文章增加或删除都会对其后的文章地址产生影响,在严格的思路下该处理方式存在问题,如果以后有时间再修正该问题。

因为是重新生成,所以原文章的点击量无法保存。

因为在 hexo 中只有 date 一项,所以发布时间和修改时间只能设置成统一的。

又因为 hexo 中没有置顶和隐藏选项,所以该功能同样被架空,置顶的问题还是需要通过博客后台来设置。