01 / 通道定位
接口层能做什么,以及它做不到什么
网页版通道把一条商品的发布拆成几个请求:创建草稿、写入字段、上传图片、提交发布。每一步都有明确的输入与返回,失败时返回里带着原因,不需要靠截图猜。这条路径适合发布量大、字段相对固定、需要并行处理的场景——比如一批二手数码按型号分好了类目与价格带,只等按节奏发出去。相对地,手机 APP 自动化通道适合那些必须在客户端里走完的发布。
必须承认接口层的边界。客户端里有很多「顺手就做了」的默认行为,接口不会替你做:图片的裁剪与压缩、某些类目下的附加字段、活动位的勾选、草稿的自动保存时机。这些不会报错,只会以「字段缺失」或「发布后信息不全」的形式出现,事后才发现。所以判断这条通道适不适合,先看三件事:
字段是否稳定
同一批商品的必填字段一致、取值来自固定枚举,接口化才有意义。如果每条都要临场决定类目与属性,写死的请求体会频繁失败。
是否接受「先草稿后提交」
接口路径一般是分步的。分步意味着中间态可以被检查,也意味着中途失败会留下草稿,需要显式清理。
是否需要跨设备并行
接口没有设备占用问题,多账号并行只受限于频率与凭证管理。这是它相对手机通道最直接的优势。
两条通道不是二选一的关系。同一份发布计划里,一部分槽位分给网页版、一部分分给手机,归属是算出来的而不是人工标注,这一点在第六节展开。如果只想先跑通一条,网页版通道的门槛更低:不需要安卓设备,也不需要处理中文输入。
还要判断一件事:你的类目在客户端里是否有接口拿不到的字段。二手数码常见的成色分级、配件清单、是否拆修,在接口层通常有对应字段;但一些偏定制化的类目,属性表单本身就是客户端拼出来的,接口传进去会被忽略。这不是接口写错了,而是两侧的字段定义不同步。上线前拿一条真实商品在两个端各发一次,比对发布后的详情页,差异就是必须补的字段清单。
另外要接受分步的代价:创建草稿、写字段、传图、提交,任何一步失败都会留下一个中间态。草稿不会自己消失,积累多了会影响后续判断——分不清哪条是计划内的、哪条是上次失败留下的。所以每轮开始前先清一次过期草稿,并且在台账里标记「已创建未提交」,不要让它变成一笔糊涂账。
- 两端各发一条同一商品在客户端与接口各发一次,比对详情页差异
- 差异列成清单差什么字段就补什么字段,不要靠印象
- 草稿有清理每轮开始前清过期草稿,避免中间态堆积
- 类目有映射业务类目名与叶子类目编号的对应表要能核对
如果一次发布失败你说不清它到底发没发出去,这条通道就还不能算上线。
02 / 凭证管理
登录态是第一条生命线,它会在你以为稳定时失效
接口调用全部依赖一份有效的登录态。它不会突然消失,而是慢慢过期:可能是几天,也可能在某次改密、换设备、异地登录之后立刻失效。失效的表现很少是干净的「未登录」,更多是返回一个看起来正常的结构,但里面没有数据,或者提示需要验证。如果不做判断,流程会安静地失败一整批。
启动时先探活
正式发布前用一个轻量请求确认登录态有效,比如读一次自己的账号信息。探活失败就不启动这一轮,而不是发到第三条才发现。
区分「过期」与「被限制」
过期可以重新登录后续跑;被限制(需要验证、操作受限)不能靠重试解决,要继续重试只会加重状态。两类返回必须分开处理。
凭证单独存放
登录态与账号配置放在独立的配置文件里,权限收紧,不进版本库、不进日志。日志里打印请求体时要过滤掉凭证字段。
还有一条经验:不要用一个账号的凭证跑另一个账号的发布计划。凭证与账号是一对一的,混用会让台账里的记录归属错乱,事后无法判断某条商品到底发在哪个账号上。多账号并行时,账号编号、凭证、台账归属三者要能互相对上,具体编排见多设备并行管理。
探活不要做成每秒一次。频繁请求本身就是一种特征,而且会在登录态真的失效时制造大量无效调用。合理的做法是每轮任务开始时探一次、连续失败达到阈值时再探一次,中间不重复探。多账号并行时,凭证按账号编号轮换读取,任何一个账号探活失败只影响它自己的槽位,不要把整批停掉。
登录态失效之后怎么续跑,也需要事先定好规则:台账里记着这个账号本轮已经成功提交的数量与最后一条的 item_id,续跑时从下一条开始,而不是把整轮重来。没有这条记录,人只能凭印象决定从哪继续,结果要么漏发,要么重复发,两种情况都要花时间收拾。
- 轮首探活每轮开始探一次,失败即不启动
- 失效可续跑台账记下已发条数与最后一条 item_id
- 凭证不共用账号与凭证一对一,配置与日志都不落明文
- 限制不重试需要验证之类的情况停下来处理,不硬试
凭证到期这件事不要靠猜周期。多数账号的登录态是在一次正常的日常操作中被判失效的,而不是到期日。所以探活结果要写进日志,带着时间戳,这样失效频率有据可查,而不是「感觉最近老是掉」。
03 / 字段契约
一次发布的字段契约,少一个字段不会报错
接口对字段的容忍度比界面宽:界面里必填的东西,接口可能允许传空,然后在展示时补默认值。结果是一条「发布成功」的商品,标题被截断、成色没标、运费模板用了默认。所以字段契约要显式定义,并且在提交前逐项断言,而不是相信接口会挡。
| 字段 | 来源 | 提交前怎么校验 |
|---|
| 标题 | 文案模块生成 | 长度在平台允许区间内,含品类词与关键规格,不含绝对化用语 |
| 描述 | 文案模块生成 | 分段完整、成色与瑕疵写清、无联系方式 |
| 价格 | 商品池 | 与计划价一致,落在该类目的价格带内 |
| 类目 | 商品池 | 属于允许清单,叶子类目存在 |
| 成色 | 商品池 | 枚举值合法,与描述里的成色表述一致 |
| 图片 | 素材目录 | 数量 3 到 9 张,主图排第一,无重复图 |
| 运费 | 账号配置 | 模板与计划一致,包邮与否不靠默认值 |
这张表的价值在于「来源」那一列:每个字段只能有一个来源。如果标题既在文案模块生成、又在商品池里手改过,最终发出去的是哪一个就说不清了,而且台账记下的可能还不是实际提交的那份。字段来源唯一,是能反查的前提。文案怎么写、怎么去重,见AI 商品文案改写。
字段契约落地的方式是一份校验函数,提交前统一调用一次,而不是散落在各处零散判断。校验不通过时返回具体是哪一项、期望什么、实际什么,这条信息要写进台账的失败记录里,否则事后只看到「字段校验失败」四个字,等于没记录。校验函数本身也要有测试用例,尤其是边界:标题正好等于上限长度、描述里带换行、价格带小数。
类目映射是另一个容易失守的地方。商品池里写的是业务口径的类目名,接口要的是类目编号,两者之间靠一张映射表。映射表一旦有过期项,表现是「部分商品永远失败」,而失败原因看起来像参数错误。映射表要跟着平台类目调整更新,并且在提交前校验叶子类目是否仍然存在。
- 校验集中一处提交前统一调用,不在各处零散判断
- 来源唯一每个字段只有一个来源,避免发出去的和记下的不一致
- 边界有用例标题正好上限、描述带换行、价格带小数都要测
- 叶子类目先验提交前确认类目编号仍然存在
04 / 图片处理
图片上传:顺序就是主图,重复就是废图
接口上传图片通常返回一个图片标识,提交时按数组顺序引用。这个顺序直接决定主图是谁——主图错了,整条商品的点击表现会完全不同,而页面本身看不出任何错误。所以顺序不能靠上传完成的先后,必须在上传前就把数组排好,上传后按标识回填,而不是按完成时间拼接。
数量在 3 到 9 张之间
低于 3 张信息不足,买家常在成色与配件上反复问;高于 9 张容易混入重复图或无关图,也超出平台常规展示位。
主图先定,再定其余
主图应该是能一眼看清商品本体与成色的那张。配件图、瑕疵特写、包装图排在后面,顺序在计划里固定,不随上传结果变化。
上传后回读校验
提交前读一次已关联的图片数量与首图标识,与计划比对。上传接口返回成功但实际未关联的情况是存在的,只看返回值不够。
还有两个实际操作里的注意点。一是同一批商品如果共用一套图,主图相似度会很高,这属于分散度检查的范围,闸门会拦;二是图片文件本身要预处理好尺寸与压缩,接口不替你做裁剪,传一张过大的原图只会拖慢上传并在展示时被二次压缩,画质反而更差。
图片在进入上传流程之前应该先统一预处理:长边缩到平台常规展示尺寸、按固定质量压缩、统一格式。这一步的意义不只是快,而是让同一批商品的画质表现一致——一批里混着过度压缩的图和未压缩的原图,展示效果差异会很大,而这类差异在数据上表现为某些链接表现异常,很难归因。
瑕疵图的位置要有规矩。二手商品的买家最关心瑕疵,把瑕疵特写排在前几张,问价会少很多;把瑕疵图藏在最后,成交后纠纷概率上升。这条规矩要写进发布计划的模板里,而不是靠每次临时决定,否则批次之间不一致,同一批货的评价也会不一致。
- 先排序再上传顺序在上传前定好,不按完成时间拼
- 主图唯一一张主图,其余按配件、瑕疵、包装排
- 数量守区间3 到 9 张,且无重复图
- 回读校验提交前读首图标识与数量,与计划比对
图片的命名也建议带上顺序前缀。上传是按数组走的,但排查时人看的是文件名,名字里没有顺序信息,就得回去翻计划表。
05 / 错误处理
失败重试要先回答一个问题:这条到底发出去没有
接口调用失败不等于没发出去。请求超时、连接被重置、响应体解析失败,这三种情况下服务端可能已经处理成功。如果直接重试,就会产生两条一样的商品,而重复商品既占用槽位,又会触发指纹去重把后续计划挡住。
先查再重试
失败后先用商品指纹(标题、价格、主图的组合)回查台账与账号在售列表。已经存在就标记为已发布,跳过重试。
区分可重试与不可重试
网络类、超时类可以重试;参数错误、类目不存在、字段超长属于确定性失败,重试只会重复失败,应当直接记失败原因并退回队列。
重试要有上限与间隔
同一商品的重试次数设上限,超过就停下来等人看。间隔不能是固定常数,否则一轮失败会变成一段密集的重复请求。
这一切的前提是台账里能按指纹查到记录。台账记录的字段包括 item_id、标题、描述、价格与时间戳,两条通道写同一处,具体口径见发布数据台账。指纹去重与合规判断是提交前那道闸门的一部分,规则细节在商品合规检查。
错误要分类,不能一律叫「失败」。网络类(超时、连接重置)可重试;参数类(字段超长、类目不存在、价格越界)不可重试,重试只会重复失败;权限类(登录态失效、操作受限)要停下来处理凭证或等状态恢复;平台类(大面积异常)要整批暂停。四类的处置动作完全不同,混在一起处理的结果是把确定性问题当成偶发问题反复重试。
重试要带退避:第一次失败后等一小段,之后逐步拉长,并且加抖动。固定间隔的重试会形成一段密集且规律的请求序列,这个特征比发布本身更显眼。重试次数到上限就停下来记一笔,交给人看,不要让它无限循环——无限循环的任务看起来在跑,实际上什么都没做成。
- 失败先查按指纹回查台账,确认没发出去再重试
- 四类分开处置网络、参数、权限、平台,动作各不相同
- 退避带抖动不固定间隔,不无限循环
- 失败写原因记下具体字段与期望值,不写「失败了」
失败记录要能直接回答「这条现在是什么状态」:未提交、已创建草稿、已提交成功、提交结果未知。四种状态对应四种处置,缺了「未知」这一档,人就会把超时当成失败去重发。
06 / 通道协同
两条通道共用一本台账,槽位归属是算出来的
同时跑两条通道时,最容易出的问题是同一个槽位被两边各发一次。解决办法不是人工标注「这条归手机、那条归网页」,而是让归属可计算:同一份发布计划进来,用同一个判定函数按账号、类目、时间窗口算出每个槽位归哪条通道,两侧读到的是同一个结果。人标注会漂移,函数不会。
槽位先于通道
先有「今天这个账号在这个时段发这个类目」的槽位,再决定由谁执行。反过来先选通道再找位置,会出现两边抢同一个时段。
台账单一写入口径
两条通道都通过同一处写台账,不允许各写一张表再合并。合并的表迟早对不上,而且对不上时无法判断哪份是真的。
执行端可替换
同一个槽位换通道重跑,业务语义不变。这意味着通道故障时可以把槽位挪到另一侧,而不需要重新排计划。
这套分工的实际收益是容错:手机设备掉线、网页登录态失效,都只影响执行端,不影响计划本身。代价是两条通道的字段契约必须一致——网页版能接受的空字段,手机端可能根本填不进去,反过来也一样。所以字段校验要放在通道之外,一处校验、两处遵守。节奏怎么排、每天发几条,见定时发布与节奏控制。
槽位函数要能被人读懂它的输出。给定账号、日期、类目,它应当返回「这一天哪些时刻、各归哪条通道」,并且这个结果可以被打印出来核对。如果归属只能从运行结果反推,那么计划出问题时没人能判断是函数错了还是执行错了。可打印、可复核,是这类判定逻辑的基本要求。
两侧并发时还要防同一时刻抢占。做法是给槽位加一个短暂的时间锁,谁先拿到谁执行,另一侧看到锁就跳到下一个槽位,而不是等。等的结果是两条通道在同一分钟各发一条,节奏上立刻出现异常。台账的去重键用商品指纹而不是标题,因为同一件货的标题在不同链接上可能被刻意写得不同。
- 槽位可打印给定账号与日期就能列出归属结果
- 抢占加锁同一时刻只有一个执行端拿到槽位
- 去重键用指纹不用标题,标题可能被刻意改过
- 换端可重跑槽位换通道执行时业务语义不变
07 / 限速节奏
限速与节奏:接口快,不代表可以快发
这是网页版通道最容易被误用的地方。因为一次请求只要很短时间,人会很自然地想「那多跑几条」。但发布节奏的限制不在接口,而在账号:短时间内密集发布同类目商品,是最典型的批量特征。系统内置的节奏约束是固定的:
| 约束 | 取值 | 为什么 |
|---|
| 每日条数 | 5 到 10 条 | 超过这个量,单账号的日均发布就明显偏离正常卖家 |
| 发布间隔 | 不少于 30 分钟,带抖动 | 固定间隔会形成可辨的时间序列 |
| 发布窗口 | 09:00 到 21:59 | 夜间发布与目标买家的活跃时段不符 |
| 单服务线 | 每日 2 条 | 同一服务线集中发布,类目与内容高度相似 |
| 周上限 | 12 条 | 把日上限与周上限一起用,避免一周堆在两天 |
这些数字要一起看,不能只守一条。只守日上限、不守周上限,结果是周一周二发满、后面五天不动,节奏上反而更异常;只守间隔、不守窗口,会出现在凌晨集中发布的情况。排计划的时候应该先按周排,再往下摊到天,最后才落到具体时刻。
还有一条独立于节奏的控制:平台健康闸。平台侧出现异常时(大面积报错、页面结构变化、接口返回异常比例升高),整批暂停,不硬发。硬发的代价是用真实商品去试探平台状态。账号安全这一层的完整做法见防封控与账号安全。
排周计划的顺序建议是这样:先定这一周的总量(不超过 12 条),再按类目与服务线分到天(单服务线每天不超过 2 条),最后在窗口内按不少于 30 分钟的间隔落到具体时刻,间隔上加抖动。抖动不要用一个常数偏移,那等于把固定间隔整体平移;应该在一个区间内随机,并且避免连续几次落在同一侧。
节假日与平台活动期要单独处理。活动期平台侧流量与审核都更紧,这时候按常规量发布容易撞在异常上。稳妥的做法是活动期降低日发量、拉长间隔,把计划往后顺延,而不是硬按原计划跑完。顺延要记进台账,否则下一周会莫名其妙超量。
- 先周后天周总量定下来再摊到每天
- 三条一起守日上限、周上限、单服务线日上限同时生效
- 间隔带抖动在区间内随机,不用固定偏移
- 活动期降速平台异常或活动期顺延,顺延要记账
还有一条容易被忽略:同一账号的发布间隔应该看「上一条实际提交时间」,而不是计划时间。计划是理想值,实际提交会因为失败重试、排队而偏移。
08 / 验收
上线前的验收口径,用数字而不是感觉
网页版通道的自检是分层的:接口层用例 82 项全过,覆盖字段契约、图片关联、返回解析与错误分支;主路径冒烟 26 项全过,从读计划到写台账走一遍完整链路;另有一组反向测试,专门验证「不该发的时候确实没发」——闸门拦截、指纹重复、登录态失效、字段超限这几种情况都必须失败退出,而不是带着错误继续。
正向与反向都要有
只测「能发出去」,等于只测了一半。反向测试证明拦截有效,这一半决定了出问题时会不会污染账号。
自检不碰生产数据
曾经发生过自检污染生产发布记录的问题,根因是路径解析早于环境变量生效。现在写生产数据前留 .bak,自检进程带标记时写生产直接抛错,整轮前后对生产文件做哈希比对。
改动后必跑一遍
82 项与 26 项的意义是回归基线。任何改动之后掉一项,就说明改坏了什么,而不是「大概是环境问题」。
- 探活通过才开跑登录态无效时整轮不启动
- 字段逐项断言标题长度、价格、类目、成色、图片数量都在提交前比对
- 失败先查再重试按指纹回查,避免重复发布
- 节奏按周排日上限与周上限一起守,间隔带抖动,窗口内发布
- 哈希比对收尾自检或批量任务结束后核对生产文件未被意外改写
这套验收做完,网页版通道可以作为主力执行端长期跑;手机通道则在那些必须在客户端完成的发布上补位,两者的关系见产品功能总览。
反向测试要覆盖到具体的失败路径,而不只是「随便传个错参数」。至少要有这四种:闸门拦截(合规命中)、指纹重复(同一商品二次提交)、登录态失效(探活失败后不启动)、字段超限(标题超长被校验挡住)。四种都必须以失败退出并写入台账;如果哪一种「成功」了,说明拦截逻辑被绕过了,这比功能缺失更严重。
收尾的哈希比对是防污染的最后一道:整轮任务开始前对生产数据文件算一次哈希,结束后再算一次,两次不一致就说明有非预期写入。这项检查在自检与批量任务里都要跑,因为一旦生产记录被污染,后面所有基于台账的判断都会错,而且错得很安静。
- 四项拦截必测合规命中、指纹重复、登录失效、字段超限
- 拦截要退出失败退出而不是降级继续
- 前后哈希比对生产文件不该被这一轮改写
- 掉项即回滚回归掉一项先停下查,不当偶发处理