本文同步发布于公众号「道雷说道」关注获取最新研究与推送
← 返回文章列表

公众号发布管线迭代实录:从「基本能用」到「不必盯着」

2026-06-01 · 约 10 分钟阅读
AI 协作 效率工具
上一篇文章写了公众号配图自动化的从零到一。一个月后再看,当初那个脚本除了"能跑"之外,哪哪都是窟窿。本文记录的是六轮迭代——不是重写,而是在同一个脚本上不断发现、修复、升级的过程。某种意义上,它比第一版的搭建过程更值得写。

为什么需要迭代

初版管线(publish-via-api.mjs)工作量大约一个下午:Pollinations.ai 生图 → 上传微信 CDN → 组装 HTML → 创建草稿。跑通的那一刻很有成就感,但很快发现这套管线只是在理想条件下能工作

实际情况是:

这些问题单独看都是小问题,但叠加起来导致一个后果:每次发布前还是需要大量手动修复。"一行命令发布"变成了"一行命令 + 半小时人工修图 + 排版调整"。那自动化省下来的时间去哪了?

所以决定:不重写,不规划大版本,用最笨的方式——发现一个问题修一个问题,修完就测,测完上线

第一轮:内容污染治理

最先暴露的问题不是图片——而是文章内容本身。

bug 1:标题候选进入正文

我的写作流程是先写「内容管线」再手动提取标题候选。markdown 文件末尾有一段:

---

## 标题候选

碳电算协同:三条线同时收紧意味着什么
当考核、碳价、算力用电同时收紧
......

buildArticleBody() 函数里有一个正则去掉 --- 分隔线。问题在于标题候选区块本身也是 ---\n## 标题候选\n...\n--- 的格式——去掉分隔线之后,## 标题候选 变成了一个正常的三级标题出现在正文中。

另一个更隐蔽的问题:这块内容同时流入了 TOC(目录生成)逻辑,导致目录里多了一个叫「标题候选」的章节。

修复:在去掉 --- 之前先用 ---\n## 标题候选[\s\S]*?\n--- 找到并整块剥离。

教训是:markdown 里的「注释区段」应该用 HTML 注释 <!-- --> 而不是依赖分隔线语法。不过改动 markdown 文件本身可能引发别的问题,我选择了让解析器更健壮。

bug 2:摘要重复

文章开头的 > 引用 是用于公众号摘要(digest)的。但这个引用同时出现在正文里——且 digest 字段也引用了同一段文字。读者打开文章看到的第一段和摘要完全一样,体验很差。

修复:在 buildArticleBody() 的产物中新增正则去掉正文首行的 > blockquote

这是一类典型的管线问题:同一份数据被两个下游以不同方式消费,但上游不知道自己被消费了两次

bug 3:TOC 编号对齐

旧版 TOC 用表格布局 + inline-block 的编号圆点,在不同手机上垂直对齐飘忽不定。修复成 flexbox 等宽圆点 + 自动换行文本,移动端横竖屏都对齐了。

这些代码改动都不大(每处 3-5 行),但它们是第一轮迭代的核心价值:扫清了「发布后才发现要改」的问题,让人可以放心地一键生成草稿。

第二轮:配图的九九八十一难

内容问题清完后,最痛的点浮出水面:配图。

第一回合:Pollinations 免费额度

Pollinations.ai 底层跑的是 Flux 模型,质量够用,也不需要 API Key——最开始生图成功率 100%。但第二天开始,第 3 张、第 4 张图开始返回 HTTP 402(Payment Required)。

尝试过的对策:

结果:前 2 张始终免费,后面的随机成功或 402。不是内容问题,是明确的免费额度限制。

第二回合:Picsum.photos 兜底

加了一个 fallback:如果 Pollinations 返回 402,就从 Picsum.photos 拉一张随机图片占位。Picsum 永远不收费,速度也快——但图是纯粹的随机风景照,跟文章内容毫无关系。

有一篇文章的配图是一张雪山照片,配文是「电力现货市场交易策略」——看起来很滑稽。

这个方案在技术上是可用的,但在内容层面不合格。

第三回合:SVG 主题插画

再往下想,如果要保证图片既免费又与内容相关,而且不需要外部 API,那唯一的路是程序化生成——用 SVG。

初版 SVG 很简单:

因为 macOS 的 sips 命令可以把 SVG 直接转成 PNG,最后转出来的图片可以在微信 CDN 上传。但说实话质量就是「看个意思」的水平。

后来设计了一套全新的 SVG 插画(我对这个迭代花的精力最多):

这三张图全部通过 SVG 手动绘制坐标、路径、渐变色,不需要任何外部图像 API。它们被 sips 转成 PNG 后上传微信 CDN,失败时用 SVG data-URI 兜底。

这件事的核心启示:不依赖任何外部生图服务的情况下,仅用代码生成的矢量图像可以达到"插图级"质量——前提是你愿意花时间在 <path> 的贝塞尔曲线上。

第四回合:微信 AI 配图 + 混合策略

之后公众号后台推出了 AI 配图功能——开启后微信会在发布时自动为正文段落配图。测试发现效果尚可,封面仍用 Pollinations 生成(可以人工选图 prompt),正文留给微信处理。

当前管线采用了四张图一次性批量生成的策略:

这是 N 次试错后的最佳性价比方案:免费的先用,免费的用完就用微信自带的,都不强求。

第三轮:排版从「能看」到「好看」

内容和配图都有了,但文章体感很糙——大段文字堆在一起,数据缺乏视觉层次。

isDataLine 收窄

最开始做了一个功能:检测包含数字和单位的段落,自动用品牌色高亮数字。但条件设得太宽,任何带数字和单位的句子都触发。结果一篇文章里三分之一内容被标红——红色失去了注意力引导的意义。

修复策略是两级收紧:

效果:数据卡从 20+ 降到了 9 个,仅真·数据段落触发红框标注。

视觉组件系统

在 mdToWeChatHtml 函数里逐步积累了一套排版组件:

这套组件通过 mdToWeChatHtml() 一个函数实现,输入是 markdown,输出是可发布的 HTML。组件设计上克制——不贪多,每种只做一种。

第四轮:质量门禁

发表了第一篇完整的管线文章后,第二天打开公众号后台发现图片裂了。原因是某个 CDN 上传成功了但返回的 URL 格式变了。

这种问题无法通过测试覆盖(因为涉及外部 API 响应格式),唯一能做的就是在创建草稿之前自动检查每个环节的输出

article-quality-gate.mjs 做的事情:

检查项不覆盖排版——排版问题靠预览 HTML 人工看。但所有可自动检查的项目在生成草稿前全部过一遍,发现问题可以原地修复而不是发布后修复。

这个门禁还有一个重要设计:--preview 模式运行时会自动触发门禁,验证通过后再去掉 --preview 正式创建草稿。不能跳过。

当前架构一览

整条管线经过六轮迭代后,最终的架构概览:

文章 markdown 文件
    │
    ▼
┌──────────────────────────────────────────┐
│  publish.mjs                             │
│                                          │
│  1. 解析 markdown 元信息(标题/摘要)      │
│  2. 配图管线(4 张批量生图)              │
│     ├─ Pollinations.ai 生图              │
│     ├─ 短提示词回落(失败时)             │
│     └─ 上传微信 CDN + 封面素材库          │
│  3. 正文生成(buildArticleBody)          │
│     ├─ 去掉标题候选区块                   │
│     ├─ 去掉首行重复摘要                   │
│     ├─ mdToWeChatHtml 渲染               │
│     │   ├─ 表格/列表/引用                 │
│     │   ├─ isDataLine 数字高亮            │
│     │   ├─ KPI 卡片/引文/容器块           │
│     │   └─ CTA 结尾                      │
│     └─ 嵌入正文配图                       │
│  4. 质量门禁(自动)                       │
│  5. 创建草稿(cgi-bin/draft/add)         │
│     └─ 返回 media_id                     │
│                                          │
│  一条命令:                               │
│  node publish.mjs --md article.md        │
└──────────────────────────────────────────┘
    │
    ▼
公众号后台「草稿箱」→ 人工审核 → 发布

这个架构的特点是:局部迭代,整体稳定。每次改动只影响一个模块,管线入口永远是 node publish.mjs --md 文件名

核心教训

迭代发生在线上,不是在规划里

这六轮迭代中,没有哪一轮是在开始之前就规划好的。每轮都是在发布后发现问题——有些读了预览 HTML 发现,有些在后台草稿箱里翻到,有些是读者告诉我的。

如果按传统的「先规划再开发」,代码只会停在第一版——因为第一版在理想条件下确实能跑。只有放到真实流水线上跑几轮,才会发现那些被理想条件掩盖的脆弱环节。

AI 协作改变了迭代成本

一般来说,一个人维护一个发布了 400+ 行 Node 脚本的迭代意愿是很低的——工作量看起来大,产出看起来小。但因为有 Sisyphus 做执行层,每次迭代的边际成本被压缩到几分钟对话。

这意味着:以前不值得修的问题,现在值得了。以前「捏着鼻子手动改一下吧」的问题,现在可以变成一行 prompt 解决。这种变化带来的不是效率提升,而是质量标准的迁移——你能容忍的「粗糙」边界在不断后退。

管线类项目不需要大版本

我们不叫它 v2 或者重写。它就是同一个文件,在持续地变好。没有大版本规划,没有架构重构计划,没有技术债务清理周。变化方式是:发现问题 → 修 → 测 → 下次发布自动用上新版本。

这听起来不像软件工程的正统做法,但对于一个人维护的生产管线来说,它可能是最优的——只要每次发布出来的文章比上一次更好,方向就是对的


管线代码在 ~/Documents/wechat-publisher/publish.mjs,文章 markdown 在 ~/Documents/codex/suan_dian/drafts/。这个流程本身也是这条管线发布的——从 Sisyphus 起草到完成,中间没有人工干预。

系列:内容管线系列
道雷说道 公众号二维码
道雷说道
每周推送投资框架与行业研究心得
深度研究抢先看
每周更新通知
互动交流探讨