从年初开始,我被公众号日更这件事折磨得够呛:选题、写稿、排版、配图、定时发布,每天至少要耗掉两三个小时,而且产出质量还不稳定。后来我干脆花了两周时间,搭了一套基于 AI 的自动发文系统,把"选题→生成初稿→质量审核→排版配图→定时发布"整条链路全部自动化了。目前这套系统已经稳定跑通了近两个月,日更没断过,今天这篇就完整复盘一下我是怎么搭的、踩了哪些坑、以及最后跑通的方案长什么样。
如果你也是一个人运营公众号、被高频更新压得喘不过气的创作者,或者想在公司里做一套内容自动化流水线,这篇文章应该能帮你少走不少弯路。我会把技术选型、核心代码、运行机制、问题排查全部摊开来讲,所有方案都基于个人或小团队的轻量场景,不需要高成本投入,也不依赖你有多深的编程功底。
1. 项目整体设计与需求拆解
1.1 先想清楚:你需要的到底是什么系统
很多人一听"AI 自动发文",第一反应是"让 AI 每天写一篇文章,然后自动发出去"。但实际操作下来,这个想法太理想化了。公众号发文不是简单地把文字贴上去点发布,它至少包含六个环节:选题策划、内容生成、质量校验、排版美化、封面与素材处理、定时推送。每一个环节都有它自己的隐性成本,自动化前必须逐个拆解清楚。
我最初的需求是:每天上午固定时间自动产出一篇 1500 字左右的原创文章,包含标题、封面、正文,并在晚上 18:00 自动发布。看起来简单,但"原创"二字意味着 AI 不能瞎编,要有信息源和逻辑骨架;"自动发布"意味着系统要能扛住公众号后台的登录态、编辑器兼容性和风控限制。
所以我在动手前先画了一张需求清单,分优先级:
- 基础功能:AI 生成草稿、自动上传封面图、自动创建图文、定时发布
- 质量保障:敏感词过滤、标题规范化、正文结构校验、字数检测
- 稳定性保障:登录态异常处理、发布失败重试、运行日志记录
- 扩展预留:多账号支持、历史数据统计、内容选题管理
这张清单是我的主心骨,后面所有技术选型和代码实现都围绕它展开。建议你也先做这一步,否则很容易做着做着就陷入"为了自动化而自动化"的误区。
1.2 方案选型:为什么没走官方接口这条路
在选技术方案之前,我第一个想到的是公众号平台有没有官方发布接口。后来查了一圈,发现这里有个关键限制:个人主体的订阅号是没有开放图文发布接口的,只有完成认证的服务号才有权限通过接口群发消息。个人订阅号如果想实现完全自动群发,官方路径走不通。
那摆在面前的选择就剩两个:
- 第三方内容管理平台,比如各种"新媒体管家""公众号助手"之类,它们底层多数还是半人工操作,定时群发功能需要付费,而且你很难把 AI 生成流程嵌进去
- 自己写脚本,用浏览器自动化技术去模拟人工登录公众号后台、创建图文、执行发布
我选了第二条路。虽然听起来有点"野路子",但它的优势非常明显:不依赖第三方服务商的接口稳定性,不受付费墙限制,而且整个系统的每一环节都在自己手里,后期想加选题、加多账号、加数据统计都很方便。
具体到浏览器自动化框架,网上比较流行的有 Selenium 和 Playwright。我一开始用的 Selenium,后来忍无可忍换成了 Playwright,原因后面详细说。
1.3 整体架构:四个模块加一个调度器
我最终跑通的系统架构是这样的:一个 Python 主程序,配合一个轻量级调度器,内部拆成四个模块。
- 内容引擎:调用大模型 API,负责选题建议和正文生成。我用的是通用大模型接口,不绑定某一家,方便随时切换和做效果对比
- 审核模块:生成完的文章先过一遍自检流程,包含敏感词库过滤、标题长度检查、正文段落完整性检查、字数统计
- 发布模块:基于 Playwright 的自动化操作模块,负责模拟登录公众号后台、上传封面、填写图文内容、设置定时发布
- 数据存储:用 SQLite 记录每次运行的状态、生成文章的标题、发布时间、失败原因等,方便复盘
调度器我用的是最简单的 APScheduler,放在同一台机器上跑,没有引入复杂的消息队列。因为整个流程本身就够串行,没必要为了炫技把架构搞复杂。
这套架构看起来普通,但工程上有一个非常重要的点:四个模块之间完全解耦。内容引擎只管生成文本,审核模块只管判断过不过,发布模块不关心文章从哪来,数据存储纯记录。这样做的好处是,任何一个环节出了问题都可以单独替换或修复,不影响其他模块。比如后来我把内容引擎从 A 模型换到 B 模型,只改了引擎内部代码,发布模块一行没动。
2. 工具选型与核心原理
2.1 大模型 API 怎么选:稳定比聪明重要
自动发文系统里,AI 生成是核心,但很多人对它的期待放错了位置。我的经验是:不要追求"生成一篇惊艳的文章",而是追求"生成一篇稳定、合格、可发布的文章"。因为自动化系统最重要的是可预期性,今天生成的能用,明天生成的也不能翻车。
我测了多个大模型接口,最终留下的评估标准很简单:
- 单次生成 1500 字左右的文章,耗时是否可控(超过 90 秒就偏慢)
- 内容是否经常跑偏主题,是否需要反复追问才能拉回来
- 接口稳定性如何,有没有频繁限流或超时
- 价格是否在可接受范围,尤其在你一天一篇甚至一天多篇的时候
实际测试下来,中文内容生成上,几个主流模型的差距并不像宣传口号那么大,关键在提示词怎么写。这套系统的提示词,我迭代了至少二十版,核心逻辑是"给模型一个明确的角色定位 + 详细的结构要求 + 禁止事项 + 示例输出"。比如我会在提示词里写明"你是一名行业观察者,文章需要包含观点、案例、操作建议三部分,每部分一个小标题,全文控制在 1500 字左右",这样生成的草稿基本能直接进入审核环节。
另外要特别注意,生成内容时最好让模型一次性输出完整 Markdown 结构,包括一级标题、二级标题、段落、加粗字段。因为后面发布模块需要把 Markdown 转成公众号后台可识别的 HTML 片段,结构越规范,转换越不容易出错。
2.2 为什么选择 Playwright 而不是 Selenium
做公众号自动发布,绕不开浏览器自动化。我最初用 Selenium,发现几个痛点:启动浏览器慢、元素定位经常因为页面更新而失效、等待机制写起来很笨重。后来换成了 Playwright,体验提升是断崖式的。
Playwright 的核心优势有几个:
- 自带自动等待机制,元素可见、可点击、加载完成这些状态都能直接等待,不用手动写 sleep
- 支持通过选择器快速定位,对公众号后台这种复杂页面适配性更好
- 内置网络拦截和请求监听,能够调试页面中的 API 调用
- 浏览器启动速度快,稳定性高,跑一周都不用重启
用 Playwright 模拟公众号后台操作,底层原理就是启动一个无头浏览器,加载公众号后台登录页,输入账号密码,通过 Cookie 维持登录态,然后像人一样点击菜单、填写表单、上传文件。虽然看起来像是在"操纵浏览器",但实际上它只是把你每天手工操作的过程自动化了,并没有影响公众号平台本身的规则。
注意:这里说的登录态维持,是指常规的账号密码登录。公众号后台本身可能有扫码登录、验证码等安全机制,操作时要做好异常处理,别一味地追求全自动而把账号搞出风控。
2.3 定时调度与运行策略:别让服务器替你失眠
定时调度这个环节,很多人觉得很简单,设个 cron 或任务计划就行了。但我在实际跑的过程中发现,定时任务只是最外层,真正要解决的问题是"任务失败后怎么办"。
我的调度策略分三层:
- 外层用 APScheduler 设置每天固定时间触发主流程
- 内层每个模块都写异常捕获,单个环节失败不中断整个流程,而是记录日志后进入重试逻辑
- 最终如果文章生成成功但发布失败,系统会把草稿保存到本地,并在日志里标记"待人工处理"
这套三层机制非常关键。因为 AI 接口有超时风险、公众号后台有偶发登录失效、网络有抖动,任何一环失败都很正常。系统要做的不是保证每次都成功,而是保证失败后你能快速知道问题出在哪、怎么恢复。
另外,定时的时间设置也有讲究。我最初设的是早上 9 点生成文章,下午 6 点发布。后来发现上午大模型接口调用高峰期,响应经常不稳定,于是把生成时间挪到了凌晨 4 点,发布还是固定在 18 点。错峰之后,生成成功率提升了非常多。
3. 核心模块实现与实操细节
3.1 提示词设计与内容生成控制
先给出一段我实际在用的生成提示词(已做脱敏简化):
角色:你是一位专注【科技数码】赛道的资深作者。 任务:基于以下选题,写一篇适合公众号发布的科普向文章。 要求: 1. 标题不超过25个字,需要有吸引力,可适当使用数字或疑问句 2. 正文结构:开头引入(说明为什么值得看)→ 主体3个小节(每个小节要有小标题)→ 结尾总结(给出可操作建议) 3. 全文约1000-2000字,语言口语化,不要堆砌专业术语 4. 禁止使用"总之""综上所述""随着科技的发展"等AI味表达 5. 正文使用Markdown格式,二级标题用##,加粗用** 选题:{topic}这里有两个细节值得展开说。
第一,每篇选题要动态注入。如果你把选题写死在提示词里,生成的文章同质化会很严重。我的做法是维护一个选题池,每天随机抽取,或者根据当天热点自动生成选题。热点怎么来?可以先用大模型对某个信息源的文章标题做摘要分析,也可以手工维护。实际操作下来,手工维护加模型自动推荐结合起来效果最好,既不会太泛,又能捕捉到新鲜话题。
第二,禁止事项必须写清楚。不限定的话,AI 很容易写出"在当今社会""随着互联网的发展"这种开头,或者每段结尾都来一句"总之"。你把禁止条款直接写进提示词,比后面写正则过滤要省事得多。我甚至会在提示词里加一句"如果某段内容你觉得没有必要,可以跳过该段,不要凑字数",这能明显减少生成的废话比例。
生成完之后,内容引擎会把完整 Markdown 文本保存到一个缓存目录,同时把标题、摘要、字数记录到数据库。审核模块马上接手。
3.2 质量审核:宁可拦错,不可放过
AI 生成的文章直接发出去是有风险的,不是内容不行,而是格式和合规性往往有问题。我的审核模块分四层过滤。
第一层是敏感词检测。我整理了一个敏感词库,包含常规的违规词、营销夸大词(比如"最""第一""绝对"这类极限词)、以及不适合在公众号上发布的内容。检测到就触发拦截,整篇文章重新生成,累计三次失败就转人工处理。这里我特别强调一下极限词,公众号平台对夸大宣传的打击力度很强,文章里出现"全球最好""顶级产品"这类词,轻则删稿,重则限流,审核时必须掐掉。
第二层是标题校验。标题长度在 10 到 25 个字符之间,不能含特殊符号,不能以"揭秘""震惊"等诱导词开头。很多 AI 生成的标题自带公众号领域的恶习,不拦住的话发布后很影响账号调性。
第三层是正文结构检查。脚本会解析 Markdown 的二级标题数量,要求至少有两个小标题,每个小节内容不少于 200 字,全文总字数在 900 到 2500 字之间。这个检查有效避免了模型偷懒生成"标题党 + 一地碎碎念"的文章。
第四层是简单的内容重复检测。我会把当天文章和前一天的做个文本比对,重复率超过 30% 就重新生成,避免 AI 出现"换汤不换药"的偷懒。
这四层过滤都放在发布前,宁可误杀,不可让不合格的内容进入发布环节。实测下来,生成的文章通过率大概在 70% 左右,剩下的 30% 会被拦截重写,最终进入人工抽检环节的比例很低。
3.3 发布模块的核心代码流程
发布模块是整个系统里最"脆弱"的部分,因为它在模拟人工操作真实平台。我给出核心流程,你可以当作参考。
先看登录部分。公众号后台登录我尽量复用已有的登录态。下面是一段简化示意代码:
from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context( storage_state="wechat_state.json" # 保持登录态的Cookie文件 ) page = context.new_page() page.goto("https://mp.weixin.qq.com/") # 判断是否已登录 if "登录" in page.title(): # 此处处理扫码登录逻辑,实际项目中建议人工参与一次 pass else: print("已保持登录状态")登录态的关键在于 storage_state 文件。第一次运行时人工扫码登录,退出前把会话状态保存下来,之后每次运行直接复用。我建议每天自动发布前先检测一次登录状态是否有效,无效则发送通知提醒人工介入。
接着是创建图文的操作。在公众号后台,创建图文需要先进入"图文消息"页面,然后点"新建图文",依次填写标题、作者、正文、封面。用 Playwright 实现时,最重要的是等待元素出现,不要用固定 sleep。
# 填写标题 title_input = page.locator("input[id='title']") title_input.fill(article["title"]) # 等待正文编辑器加载完成,富文本编辑器一般有专属的iframe editor_frame = page.frame_locator("#ueditor_0") editor_frame.locator("body").click() page.keyboard.type(article["content_html"]) # 正文以HTML片段形式填入这里有个大坑:公众号后台的正文编辑器是 iframe 嵌入的富文本编辑器,直接往页面主 DOM 里填内容是没用的,必须切换到 iframe 内部去操作。而且从 Markdown 转换过来的 HTML 不能原封不动地粘贴,因为编辑器自带样式,直接粘 HTML 会导致格式混乱、图片丢失。我在系统里专门写了一个 Markdown 转公众号 HTML 的转换器,把标题、加粗、列表、引用这些基础标签转出来,图片统一用网络图片链接,封面则直接上传素材库。
发布环节我选了"定时发布"而不是立即发布。操作方式是在编辑器页面勾选"定时群发",设置好日期和时间,然后点确定。这样的好处是,即使发布模块在早上运行,也能顺利完成操作,不需要在晚上真实群发时间点再跑一次脚本,降低夜间任务失败的风险。
3.4 素材与封面处理:别让图片成为断点
图片是整个自动化链路里最容易被忽略、又最容易翻车的环节。公众号正文里的图片,官方要求上传到素材库后生成永久链接,直接外链图片在多数情况下会失效。所以我的系统会在发布前把正文里所有图片下载到本地,然后通过 Playwright 调用后台的上传素材接口,把图片传到公众号素材库,再把返回的 URL 替换到正文 HTML 中。
封面图我采用了更简单的策略:提前准备一批通用封面模板,每天随机选一张,然后把当天文章标题通过 Python 的 Pillow 库绘制到封面图上,生成一张"标题定制封面"。这样做的好处是封面永远不会缺图,而且每天的封面都有辨识度。Pillow 的操作不复杂,重点注意中文字体路径的指定,系统默认字体是不支持中文的,不指定字体画出来全是方块。
这里我踩过的一个坑是图片格式:公众号后台支持 JPG、PNG 和 GIF,但要求图片大小不超过 10MB。AI 生成的图片或者从网络下载的图片,经常出现尺寸过大或格式不规范的问题,所以图片处理模块里一定要加一步压缩和格式转换,统一转成 JPG 并压缩到 1MB 以内,既快又稳。
4. 常见问题与排查技巧
4.1 登录态频繁失效怎么办
这是自动发布系统里最让人崩溃的问题。我最初以为保存一次 Cookie 就能一劳永逸,结果公众号后台的登录态有时两三天就失效一次。失效后脚本还在继续跑,发布环节直接卡住,浪费一整天的运行额度。
我的解决方案是双保险。第一,每次运行前先做登录态检测,判断方法很简单:访问公众号后台首页,如果页面跳转到登录页,就说明 session 失效了。第二,失效后不直接退出,而是通过企业微信机器人或者邮件发送告警,提醒我人工扫码登录一次。注意,这里不要试图完全靠算法绕过验证码,风险太大,也不符合平台规则。人工扫码虽然需要一点介入,但一套号一天只需要一次,完全可接受。
另一个提高登录稳定性的办法是固定运行环境。不要频繁更换登录 IP,不要用数据中心代理,尽量让脚本在一个稳定的网络环境里跑。频繁切换环境非常容易触发风控。
4.2 富文本编辑器内容错乱怎么排查
运行期间我遇到过一次很诡异的问题:AI 生成的正文通过脚本填入编辑器后,段落之间的空行全部消失,整个文章挤成一坨。排查半天,发现不是 Markdown 转换的问题,而是写入 HTML 时没有把换行符处理好。
公众号编辑器对段落分隔很敏感,它认
标签,不认 \n。你如果用 keyboard.type 直接输入包含 \n 的文本,浏览器会自动把连续换行吞掉。解决办法很简单:在转 HTML 阶段,把所有段落用
包裹,段落之间不要留空白文本,这样编辑器就不会重新排版。
还有一个关联问题:如果正文 HTML 里有特殊字符(比如 &、<、>),直接填入编辑器会被转义成乱码格式。我写了一个 HTML 转义函数,把这些字符全部替换成对应的实体,发布后效果就正常了。
4.3 定时任务为什么总是不触发
APScheduler 在单机环境下跑,遇到过两种情况。第一种是时区问题,Asia/Shanghai 时区没有显式配置时,调度器会用本地时区,但如果你把服务器设在别的时区,定时就会偏差几个小时。第二种是任务被上一次的长耗时耽误了,APScheduler 默认是串行执行,如果文章生成这个环节跑了太久,下一个任务的时间点就会被顶掉。
我的解决方法是:调度器里设置 misfire_grace_time,允许任务延迟补跑;同时把生成任务和发布任务分开两个调度器实例,生成失败不影响发布。更重要的是,每次调度跑完都往数据库写一条状态记录,第二天早上检查昨晚的运行状态,有任何异常都能从日志里翻出来。
4.4 常见问题速查
| 问题现象 | 可能原因 | 处理建议 |
|---|---|---|
| 登录页反复出现 | 登录态过期或 IP 变化 | 检查 network 环境,重新扫码登录并更新 storage_state |
| 内容生成超时 | 大模型接口限流或网络慢 | 增加重试机制,错峰调用,降低单次字数要求 |
| 编辑器正文无换行 | HTML 段落标签缺失 | 用 包裹段落,去掉裸换行符 |
| 图片不显示 | 封面/正文图片外链或尺寸超限 | 统一走素材库上传,压缩到 1MB 内 |
| 定时发布没触发 | 调度时区冲突或任务串行阻塞 | 设置 misfire_grace_time,分离调度器 |
| 公众号文章被判营销 | 极限词或诱导词未过滤 | 把极限词加入敏感词库,发布前强制校验 |
4.5 从失败里攒出的几条经验
我再补几条常规教程里不会写的东西。第一,自动化脚本的异常信息一定要往日志文件里写,同时连同运行时间、文章标题、当时的截图一起保存。Playwright 自带 page.screenshot(),每次失败时截张图,问题能少排查一半时间。我遇到过编辑器按钮在某个版本里改了 id,如果没有截图,光看报错信息完全猜不到是按钮定位失败。
第二,不要把系统设计成"失败后马上重试很多次"。公众号后台有风控机制,短时间密集操作很容易被判定为异常行为。我的策略是:单个步骤最多重试两次,间隔不少于五分钟,两次都失败就停下来等人工。
第三,一定要给 AI 生成的内容留一条人工复核通道。完全没人看的自动发文,跑久了很容易在内容调性、真实性上跑偏。我每周固定抽一天,把本周 AI 生成的文章人工过一遍,标记质量问题并反哺到提示词里,生成质量每周都有提升。
5. 后续演进与个人体会
5.1 这套系统还能怎么扩展
跑通之后,我把这套系统做了一些扩展,方向你可以参考。
第一是选题的智能化。当前是"手工选题池 + 随机抽取",最近在做的是通过对历史文章的数据分析,统计阅读量与标题关键词的关系,然后让 AI 根据历史爆款特征自动生成新选题,形成一个简单的正反馈循环。
第二是多账号支持。公众号矩阵运营的话,只需要把账号配置改成多实例,每个账号独立的 storage_state 和内容池,发布模块用参数控制运行哪个账号就行。目前我的调度器已经支持了,但还没有大规模跑起来,还在观察稳定性。
第三是数据复盘自动化。系统每天记录文章的发布时间、字数、标题、是否定时成功,再加上公众号后台的数据导出,做一个周维度的阅读趋势表。这里就是简单的 SQL 查询加 Excel 输出,技术上没有难点,但对内容策略的帮助非常大。
5.2 我对自动化发文的一些看法
总的来说,这套系统想要做到"全无人干预"其实不现实,也不应该追求。公众号平台有它的规则和风控逻辑,完全绕过人工的自动化长期看风险大于收益。更合理的定位是"AI 完成 90% 的重复劳动,人只负责判断和决策"。
你会发现,最终跑下来,每天需要人工参与的时间其实不到十分钟:早上看看生成的文章有没有问题,晚上看一眼有没有正常发布,偶尔登录一下后台处理异常。对日更创作者来说,这十分钟的成本基本可以忽略。
最后再分享一个我踩过几次坑之后总结的细节:任何自动化系统,最先要被自动化的一定是"故障发现"这件事。我的系统里写得最用心的不是生成代码,而是那几条告警逻辑和日志记录。只要故障能被及时看见,系统就永远是可靠的系统;如果故障要靠读者留言才知道,那这套自动化还不如不搭。
希望这篇复盘能给你一些参考,也欢迎你在搭建过程中遇到问题随时交流。