用Claude+Hugo博客仓库+Python脚本写技术文章:AI负责判断,脚本负责确定性操作
Contents
起因
这个博客最早写文章全靠手工:开编辑器、复制上一篇的 front matter 改日期改标题、图片一张张压缩改名丢进 static 目录、写完了本地跑一遍 hugo 看有没有编译报错。日子久了慢慢攒了几十篇文章,头部格式却越写越乱——键名顺序不统一、日期格式忽而带引号忽而不带、分类名想到什么写什么,同一个方向能冒出三四个不同的分类名。
后来先解决了"人工写"这一半:写了几个 Python 脚本(aipost.py/aiimage.py/fix_frontmatter.py 等)把头部格式和图片入库规则定下来,配一个 Tkinter 小编辑器(hugohelper.py)保存时自动套用约定,格式统一的问题算是解决了。
但真正让整个流程提速的,是把"文章怎么写"这件事也交给 AI 来做。现在的流程是:我把想法、素材(截图、参考资料、别人的文章链接)扔给 Claude Code,告诉它要写什么方向、哪个分类,剩下核实资料、组织结构、调脚本生成文件、跑 hugo 校验这一整套都是 AI 自己完成的。这篇就整理一下这套"Claude + Hugo 博客仓库 + Python 脚本"的写作流程,包括用到的脚本代码——服务器地址这类敏感信息已经去掉。
整体思路:让 AI 遵守约定,而不是重新发明约定
这套流程能跑起来,关键不是 AI 有多聪明,是这个仓库本身先把"规则"用文件的形式固定下来,AI 读了规则文件就知道该怎么干活,不用每次对话重新解释一遍。具体落地成三层:
- 约定层:仓库根目录的
README.md记录了 front matter 格式、12 类固定分类体系、正文结构模板、图片入库规则。这是给人看也是给 AI 看的"施工规范"。 - 脚本层:
tools/目录下的 Python 脚本把约定变成可执行的操作——建文章、存图片、查/修头部问题、部署上线,每个脚本都是无 GUI、能被命令行直接调用、有明确的退出码。 - 执行层:Claude Code 读 README 和脚本源码理解规则,读用户提供的素材/参考资料,必要时上网核实信息,写好正文调脚本生成文件,最后跑一次
hugo构建校验有没有格式错误。
三层分开的好处是各司其职:约定改了只改 README,脚本不用大动;AI 换一次对话、换一个模型,只要还认得这个仓库的 README 和脚本,产出的文章格式照样统一。这也是为什么脚本里专门写了 find_blog_root() 这类函数——不管从仓库哪个子目录调用,都能自动定位到博客根目录,AI 不需要精确知道自己"当前在哪"。
核心约定库:blogutil.py
所有脚本共享的规则都收在这一个文件里,不直接运行,被其余脚本 import。核心是三块:12 类分类白名单、front matter 生成/解析函数、图片 MD5 入库函数。
|
|
后面还有 save_image()(MD5 入库图片)、unique_post_url()(生成 /p/YYYY/MM/DD.html 并按同日冲突自动加 -HHmm 后缀)、build_front_matter()(拼出规范的 YAML 头)这几个函数,是 aipost.py/aiimage.py 真正调用的部分。
图片交给脚本处理,不是交给 AI 处理
这一步是这套流程里我觉得设计得比较对的地方:插图这件事,从头到尾都是 Python 脚本在干活,AI 只负责告诉脚本"存哪张图",从不接触图片的二进制内容本身。
具体流程是:图片文件(截图、实拍照片)直接扔给 aiimage.py,脚本读文件字节、算 MD5、按哈希存到 static/uploads/images/、打印出 /uploads/images/<hash>.<ext> 这个 URL;AI 拿到这行 URL 文本,往正文里插一行  就完事了。整个过程里,图片的像素数据只在脚本和文件系统之间流转,从来不会被编码成文本进大模型的上下文——一张几百 KB 的图片如果非要用 base64 塞进对话上下文,会占掉大量 token,还容易因为长度触发截断或者速率限制。用脚本做这一层"图片 I/O",纯粹是文件路径和一行 URL 字符串的往来,AI 那边几乎不产生额外开销。
去重也是脚本层免费带来的好处:同一张图不管上传几次,MD5 一样就是同一个文件名,不会在 static 目录里堆出一堆内容相同、文件名不同的垃圾文件。这对靠 AI 反复迭代文章、经常"这张图不满意换一张再插一次"的场景尤其有用,不用手动清理废弃图片。
|
|
|
|
命令行用法很直接:
|
|
生成文章:aipost.py
正文写好之后,交给 aipost.py 生成规范的 front matter 并落盘。这一步的关键是分类校验——aipost.py 只认 blogutil.CATEGORIES 里的 12 个分类,写错分类名直接报错退出,不会静默创建一个新分类污染全站的分类体系。
|
|
用法很简单,AI 把正文写到一个临时文件,调一次脚本:
|
|
--dry-run 这个开关在 AI 协作场景里很有用——正式写盘前先打印一遍生成结果,AI(或者我)看一眼头部对不对、分类对不对,确认没问题再去掉这个参数真正落盘,避免格式错了还要再手动改文件。
写完不代表能用:跑一次 hugo 构建校验
AI 生成的 Markdown 文件,格式对不对不能靠"看着像",得让 Hugo 自己编译一遍。这个仓库的头部格式有几个容易踩的坑:type: post 漏写会导致 even 主题不显示标题;categories/tags 用了流式列表或者缩进不对会导致 YAML 解析异常;重复键、悬空列表项直接让 hugo 编译报错退出。这些问题光靠人眼扫一遍正文很容易漏,但 hugo --quiet 编译一遍,有问题立刻能看到报错信息。所以流程里最后一步永远是本地跑一次构建:
|
|
没有报错输出就说明这篇文章的 front matter 和正文 Markdown 语法都合法,可以准备发布。如果头部历史遗留问题比较多,还有专门的巡检脚本先跑一遍干跑模式,确认要改的地方再决定要不要 --write:
|
|
部署:deploy.py(服务器地址已隐去),实际用起来就是一条命令加一次密码
文章确认没问题之后,最后一步是把 hugo build 生成的 public/ 目录同步到服务器。这一步现在对我来说体感上是"一键搞定":命令行敲一条 python tools/deploy.py,脚本自己跑 hugo build、自己算本地和远程的文件差异、自己决定要传哪些要删哪些,我只需要在它连接服务器那一刻手动输一次 SSH 密码,剩下全程不用管。构建、比对、上传、清理空目录,一条命令全包了,不用再手动敲 hugo→打开 FTP 工具→逐个文件对比上传这一套。
脚本用的是"内容 MD5 比较"的增量同步策略,效果上等价于 rsync --checksum --delete:本地和远程按文件内容哈希比较,一样的文件跳过不传,本地已经删掉的文件远程也同步删除,保证线上内容和本地仓库完全一致。
|
|
差异算出来之后再决定上传哪些、删除哪些:
|
|
几个安全细节值得说一下:
- 密码不落盘、不写进命令行参数:每次运行在控制台手工输入(
getpass.getpass),或者临时设置环境变量DEPLOY_SSH_PASSWORD跳过交互,但不建议写进 shell 历史 - 删除操作有二次确认:远程有本地已经没有的文件,会先列出来问一遍要不要删,除非显式传
--yes - 有
--dry-run:正式同步前先看一遍会传哪些、删哪些,不做任何实际改动
|
|
远程主机地址、路径这类信息写在脚本顶部的几个常量里(REMOTE_HOST/REMOTE_USER/REMOTE_ROOT),这篇贴出来的代码去掉了具体值。
现在的完整流程长什么样
拼起来,一篇文章从"我有个想法"到"发布上线",现在走的是这条链路:
- 我把想法、素材(截图、参考链接、别人的文章、自己的研究笔记)扔给 Claude Code,说清楚想写什么方向
- AI 读
README.md和tools/下的脚本理解格式约定,读我提供的素材,需要核实的地方自己上网搜证据(比如某个芯片型号、某个产品的官方参数),不确定的地方会用问题的方式跟我确认(比如该归哪个分类、某个没有来源的说法要不要收进去) - 图片用
aiimage.py入库拿 URL,正文写好存临时文件 aipost.py生成规范 front matter 并落盘,打印文件路径和 urlhugo --quiet跑一遍构建校验,删掉临时文件- 确认没问题后跑一条
python tools/deploy.py,输一次密码,博客更新到线上——部署这一步也是一键搞定,不用再手动传文件
以前这六步里,第 1~4 步全靠我自己一个字一个字敲;现在变成我给方向和素材,AI 处理组织结构、资料核实、格式生成这些体力活,我看结果、拍最终的分类/取舍决定就行——写一篇有实测数据、有参考链接核实过的技术文章,从想法到能发布,压缩到一次对话的时间。
解决的另一个老问题:写一半烂尾
平时工作忙,博客写一半放着的情况不少见——开了个头,起因写完了,正准备写技术细节,一忙就是好几周,回头再看已经忘了当时想表达什么,索性放弃。这个仓库甚至专门有个脚本在跟踪这类烂尾文章:
|
|
现在跑一下这个脚本,仓库里还有 26 篇文章带着 stub: true 标记——这些都是当年开了头没写完的坑。有了现在这套流程之后,这类烂尾基本不会再发生了:我不需要憋出完整的思路和文字,只要给一个大概的方向和几个关键词,一次对话内就能落地成一篇结构完整、有理有据的文章。前面几篇(电子价签改造、闲鱼算力板、GPT+KiCad)都是这么来的——起因就是几句话的念头,剩下组织结构、核实资料、写完整篇的活儿都在一次对话里完成,不存在"改天有空再写"这个中间状态,自然也就不会烂尾。
额外收获:技术文章顺带成了整理好的开发日志
用下来还有一个没预料到的好处:AI 写出来的东西,条理天然比我自己手写清楚。 排查一个问题、折腾一套方案的时候,人写记录很容易图省事——想到哪写到哪,踩了三个坑混在一段话里,最后"解决办法"和"当时走过的弯路"分不清楚。让 AI 来整理这些素材就不一样:它会很自然地把内容拆成"现象是什么"“根因是什么"“解决办法是什么"这样结构化的小节,同一类信息聚在一起,而不是按时间线原样堆叠。
这篇文章本身其实就是个例子。前面几篇(电子价签改造、闲鱼算力板、GPT+KiCad)在整理过程中,素材是我零散给的截图、卖家描述、参考文章链接,AI 组织出来的是"起因→识别方法→操作步骤→踩坑记录→总结"这样分好类目的结构,遇到卖家说法和实测不一致的地方(比如价签芯片型号、KiCad 演示的具体出处),也是先分门别类核实完再收进对应小节,不是原样照抄谁说了什么。这个整理能力放到日常开发记录上同样好用:调试笔记、方案对比、踩坑经历,交给 AI 整理一遍,比自己手写的版本更容易过后回头查。
总结
这套流程能跑起来的核心不是"AI 会写文章”,是这个仓库先把格式约定、图片规则、分类体系用 README.md 和几个 Python 脚本固化下来,AI 只是照着这套规则干活的执行者。图片处理这类纯 I/O 操作交给脚本,靠内容 MD5 去重、不占用 AI 的上下文 token;生成文章、部署上线也是脚本收口,AI 负责调度和产出内容本身。这种"AI 负责判断和内容,脚本负责确定性操作"的分工,是这条流程好用、稳定、还不烧 token 的关键。
参考链接
- 仓库根目录
README.md——博客的完整写作约定:front matter 格式、12 类分类体系、正文结构模板 - 仓库
tools/README.md——全部脚本清单与参数说明
Author 软件开发大郭
LastMod 2026-09-09