前言

timqian在Github上收集中文独立博客,提到独立博客虽已式微,但爱其“自由的排版,自由的说话”。

将自己的独立博客提交到列表的时候,timeqian提醒我RSS似乎有误,于是修理了一下博客工具(五年前的版本),不修还好,修理之下问题越来越多,一咬牙,决心切换到Hugo,文章有点多,只好写了自动迁移脚本,结果编译速度从一分钟下降到了3秒不到(591篇文章)!终于甩掉了6年前的老旧风格,换上自己喜欢的干净主题

犹豫的原因

在静态博客生成器中,Hugo口碑很好,速度快是其核心优势, slogan是

The world’s fastest framework for building websites.

迟迟没有迁移的原因有二:

  1. 需要调整meta数据(categories,tag,Slug…)
  2. 兼容旧的链接(外部引用或者搜索结果)
  3. 需要迁移自定义的东西(访客统计脚本等),忘了当初在哪做的配置

这些工作想想就觉得费时。

动手

meta数据

既然决定动手,便先在Google/Github上搜罗了一圈,看看前人都是如何吃螃蟹的,提前了解一下风险,也看看社区里是不是已经有自动化迁移工具了。

首先注意到了pelican-to-hugo.py

这个脚本似乎能帮我解决第一个问题:

需要调整meta数据(categories,tag,Slug…)

使用正则表达式,批量替换meta数据。

虽有些地方需要调整,但有了这个骨架,剩下就是一些细活了,我的正则表达式功底还不错(推荐《精通正则表达式》),调整起来很快。

对文件和路径的处理,我都采用pathlib,代码比前头要整洁。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pathlib import Path

p = Path(path)
files = list(p.glob('**/*.md'))

for file_p in files:
        # print(file_p)
        content = file_p.read_text()
        content = xxx(content) # 业务逻辑
        file_p.write_text(content)

兼容旧的链接

Hugo为文章生成url有它的默认规则。

我希望旧的文章保持和之前同样的url,因为搜索引擎近期搜出的文章还是老旧的连接,不希望用户搜出我的博客文章后,打开却是404。此外也希望保持对被人引用的兼容。

如果你在不同时间内阅读过腾讯开发者文档,就知道url改来改去是多操蛋的一件事了。真令人生气。所以我现在尽量回避腾讯生态的技术设施。

hugo有两个meta信息允许你自定义文档url,其一是slug, 其二是aliasesslug。我们来看个例子.

1
2
3
4
5
6
---
Date: 2019-09-09
title: "开源项目与开源社区"
Slug: about-opensource
aliases: ["/about-opensource","/about-opensource.html"]
---

这篇文章分别可以使用以下链接访问:

1
2
3
4
https://blog.just4fun.site/post/编程/about-opensource/

https://blog.just4fun.site/about-opensource
https://blog.just4fun.site/about-opensource.html

slug和目录结构有关。

aliases的左右类似重定向,这样就能很好做到兼容。aliases是我用正则表达式自动生成的。

迁移自定义的东西

这部分倒简单,原因是hugo有庞大的社区,所以像统计脚本之类的,都只需要做个简单配置就行。

更多

既然已经对博客大动刀子了,索性不如来个彻底,把想做却迟迟没有实施的事情一并做了。

此前博客图片一直放在qiniu上,为此还写了一个自动化截图工具

七牛是很好的云服务,对开发者也友好。但和国内所有的事情一样: 政策风险太高,哪天说不能访问就不能访问,诸如前段时间的leancloud,这些都不是技术问题。

所以我决定让博客尽可能自托管,其中核心的一个工作是将图片自托管。于是写了一些简单的正则表达式,提取出所有图片:

1
2
ack -ho "http:[^\(\)\[\]]*?\.(png|jpg|jpeg|gif|PNG|JPG|JPEG)" > /tmp/blog_img_list.txt
ack -ho "http://.*?.(mp4|MP4)" > /tmp/blog_mp4_list.txt

使用wget下载到hugo文件目录里。

1
2
3
4
5
6
7
import subprocess
with open("/tmp//tmp/blog_img_list.txt") as png_url_list:
    urls = set(png_url_list.readlines()) # 去重
for url in urls: 
    if "just4fun" in url:
        cmd = f"wget {url}"
        subprocess.call(cmd,shell=True)

参考