很多自动化项目在演示阶段只需要完成三件事:打开网页、填入内容、点击发布。但一旦进入真实运营环境,系统面对的就不再是一篇文章、一个账号和一个平台,而是成百上千个任务、不同平台的额度差异、随时失效的登录状态,以及无法预测的审核和网络波动。此时,决定系统能否长期运行的,不是“自动点击”写得多快,而是任务、数据和状态能否被准确地管理。
本文从工程实践出发,拆解一个可恢复、可扩展的多平台内容发布系统应具备的关键能力。
一、先把内容生产与平台发布分开
内容生成与网页发布是两种完全不同的工作负载。前者主要消耗模型调用和文本处理资源,可以并行执行;后者受账号额度、浏览器会话、平台限流和审核规则约束,必须有节奏地提交。如果把两者绑在一个脚本中,任何一次登录失效都会让整批任务中断,也很难判断失败发生在生成阶段还是发布阶段。
更稳妥的做法是划分三层:
- 内容层:保存客户资料、关键词、模板、标题、正文和图片等确定性数据。
- 调度层:根据平台额度、账号健康度和任务优先级决定何时由哪个账号发布。
- 适配层:每个平台拥有独立适配器,只负责把标准文章转换为该平台需要的页面操作和字段。
这三层之间通过稳定的数据结构通信。平台页面改版时,只需要修复对应适配器,不应该影响内容生成和其他平台。
二、用不可混淆的数据关系保护内容
批量发布最危险的问题不是失败,而是“发布成功但内容串了”。例如标题属于客户甲,正文却来自客户乙;或者同一篇文章错误地分配给两个账号。解决方式是从任务创建开始就建立不可变的关联链:
| 对象 | 必须保存的关键字段 | 作用 |
|---|---|---|
| 客户 | customer_id、品牌资料版本 | 确定内容归属 |
| 关键词 | keyword_id、原始词 | 保留生成来源 |
| 文章 | article_id、标题、正文哈希 | 防止内容被替换 |
| 发布任务 | job_id、article_id、platform、account_id | 固定发布目标 |
| 发布结果 | 平台文章 ID、链接、提交时间、状态 | 支持精确回查 |
调度器只移动“发布任务”,不临时拼接标题和正文。真正提交前再次校验文章哈希、客户归属和账号绑定关系,就能在高并发下避免跨客户串稿。
三、状态机比一个成功标记更重要
平台点击“发布”后,页面可能返回已提交审核、草稿保存成功、发布成功,也可能因为网络超时而没有明确结果。若系统只有“成功/失败”两个状态,超时后直接重试就可能造成重复文章。
一个实用的状态机可以包含:
- pending:等待调度;
- preparing:正在打开编辑器并填充内容;
- submitting:已发起提交,结果尚未确认;
- reviewing:平台已接收,正在审核;
- published:已获得可验证的文章 ID 或公开链接;
- retryable:确认未提交,可在退避后重试;
- manual_required:登录验证、账号权限或规则变化需要人工处理;
- rejected:平台明确拒绝。
其中最关键的是 submitting。处于这个状态的任务不能立刻再次点击发布,而应先去文章管理页按标题、时间、作者和内容指纹回查。只有确认平台没有收到,才允许重试。这就是发布链路的幂等保护。
四、额度调度要面向账号,而不是面向平台
不同账号的每日额度、可用时间和风险状态并不相同。即使同属一个平台,也不能简单地把总任务平均分配。调度器应持续计算每个账号的可用容量:
可用容量 = 每日软额度 - 今日已确认提交数 - 已占用任务数
调度优先级 = 客户优先级 + 等待时长 + 截止时间权重 - 账号风险权重
当新账号加入时,系统重新计算容量,尚未提交的积压任务可以立即分配给新账号;已经绑定并进入 preparing 或 submitting 的任务则不迁移。这样既能提高吞吐量,也不会让同一篇文章在多个账号之间漂移。
额度最好分为“平台硬限制”和“系统软限制”。硬限制来自已知规则,软限制由运营人员根据账号表现配置。达到软限制后自动顺延,第二天额度窗口重置时继续处理,无需重新创建任务。
五、登录会话需要成为可观测资产
无人值守不等于忽略登录状态。Cookie 和本地存储应按“平台 + 账号”隔离保存,并进行加密;每次领取任务前先做轻量健康检查。账号状态至少要区分可用、即将过期、需要登录、需要验证、受限和停用。
浏览器进程也不宜无限增加。常见做法是建立小规模浏览器工作池:同一账号串行提交,不同账号在平台允许的范围内并发。每次任务完成后释放页面而不是销毁整个会话,这能显著降低内存消耗。对于需要人工扫码或验证码的账号,只暂停该账号,不阻塞其他正常账号。
六、每个平台都要有独立契约
平台适配器不应只暴露一个 publish 函数,而应形成清晰契约:
- authorize:登录并验证账号身份;
- prepare:打开编辑器、填充内容并读回校验;
- commit:执行一次不可重复的提交动作;
- reconcile:从文章管理页或公开页确认结果;
- diagnose:把页面异常转换为统一错误类型。
适配器还应声明自身能力,例如是否支持 Markdown、是否要求封面、图片数量范围、标题长度、每日建议额度、提交最小间隔和是否支持后台回查。调度器读取这些能力,而不是把平台规则写死在主流程里。
七、自动化测试要覆盖“结果”,不只覆盖“点击”
页面自动化最容易出现一种假成功:按钮确实被点击,程序也没有报错,但文章并未进入平台列表。完整测试至少包含四级验证:
- 单元测试:标题截断、内容转换、URL 和文章 ID 解析;
- 页面契约测试:控件定位、必填项和错误提示是否仍然存在;
- 真实小流量测试:用唯一标题提交一篇文章;
- 回查测试:在账号后台定位该标题,记录审核状态和平台 ID。
若平台改版导致契约测试失败,应自动熔断该平台的新提交,只保留回查能力,并通知技术人员维护对应适配器。这样一次改版不会演变成大规模错误发布。
八、可观测性决定系统是否可运营
每天处理数万篇内容时,运营人员不可能阅读每一条日志。他们需要看到的是:今日生成量、待发布量、审核中数量、成功率、各平台剩余额度、异常账号数,以及哪些任务需要人工处理。技术人员则需要更细的证据,包括页面截图、关键响应、错误分类、重试次数和适配器版本。
建议为每次提交生成唯一 trace_id,并贯穿文章、任务、账号、浏览器会话和发布结果。出现问题时,可以从一条结果反向定位整条链路,而不是在大量日志中猜测。
九、从小规模开始验证吞吐量
无人值守系统不应第一天就追求最高并发。可以先让每个平台、每个账号以保守额度运行,积累成功率、平均耗时、审核时长和异常类型,再逐步提高并发。吞吐量估算可以使用一个简单模型:
日吞吐量 ≈ 可用账号数 × 单账号软额度 × 账号可用率 × 提交成功率
真正的扩容瓶颈往往不是电脑配置,而是账号容量、平台规则和失败恢复效率。只有当浏览器工作池的 CPU、内存或网络成为主要限制时,才需要增加执行节点。调度层保持中心化、执行层可以横向扩展,就能让新机器加入后自动领取任务。
结语
可靠的多平台发布系统,本质上是一套带外部副作用的分布式任务系统。它既要追求自动化,也必须尊重不确定性:登录可能失效、页面可能改版、请求可能超时、文章可能进入审核。通过内容与发布解耦、不可变的数据关联、明确的状态机、账号级额度调度、幂等回查和独立平台适配器,可以把这些不确定性限制在可恢复的边界内。
当系统能够准确回答“这篇文章属于谁、准备发到哪里、当前处于什么状态、是否已经被平台接收、下一步由谁处理”时,它才真正具备规模化运行的基础。
