把人工经验写成脚本需求,例外情况不能只写“特殊情况特殊处理”,而要写成“触发条件 + 判定依据 + 脚本动作 + 人工接手出口”。触发条件决定脚本是否介入,判定依据决定它信哪份数据,脚本动作决定它改什么、记录什么,人工接手出口决定它什么时候停下来等人。缺少任何一项,开发只能靠猜,脚本上线后要么误改,要么遇到例外直接报错中断。
规则内的例外,是同一套判断逻辑下参数不同,比如标题长度上限对某些栏目放宽,脚本仍可自动处理,只是阈值需要配置化。规则外的例外,是判断逻辑本身不成立,比如某个页面根本没有可替换的字段,或者页面类型尚未纳入这套规则,脚本应当跳过并记录,而不是硬套默认值。
这两类例外的写法完全不同。规则内的例外写成可配置参数:max_title_length = 30,并注明哪些栏目取30、哪些取60。规则外的例外写成前置守卫:if page_type not in supported_types: skip_and_log()。如果把它们混在一起写,开发会把本该跳过的页面当成可处理的页面,用默认值覆盖,结果比不处理更糟。
触发条件回答“什么情况下这条例外生效”,判定依据回答“脚本凭什么认为它生效”。两者都不写,等于把判断权交给开发,而开发手上没有你的业务上下文。
假设情境:某站有一批产品页,人工经验是“标题里品牌词靠后时,把品牌词提到最前”。现在要把这条经验写成脚本需求,但站点刚改过栏目结构,部分产品页的品牌词来自另一个字段。这个变化就是关键前提。
变化前,品牌词只有一个来源,脚本直接读该字段即可。变化后,同一视觉位置上的品牌词可能来自两个字段,脚本必须先判断用哪个。此时例外描述应当写成:
这样写,开发不需要猜“品牌词到底从哪来”,测试也能构造出三种输入分别验证。判定依据里的优先级顺序,是整条需求里最容易被省略、也最容易导致误改的部分。
写完例外描述后,不要直接交给开发,先用一份假设数据自查。假设有五个页面:三个品牌词在字段A,一个只在字段B,一个两个字段都为空。按上面的描述,预期结果是三个和那一个共四个页面被处理,第五个被跳过并记录。
如果自查时发现“两个字段都为空”的页面数量远超预期,说明这不是例外,而是常态,规则本身需要重新设计,而不是继续加例外。这个判断会直接影响下一步:是继续细化脚本,还是先回到人工流程把字段来源统一。反过来,如果某个例外在所有页面里只出现一次,就要考虑它是否值得写进脚本,还是交给人工单独处理更省成本。
这里有一个容易被忽略的点:改动前后做比较时,要考虑季节和搜索需求变化,不能把某段时间的数据波动直接归因于脚本改动。同理,抓取量或请求量归零,也不能单独证明脚本处理正确,还可能是采集口径变化、页面被合并或抓取被临时限制。例外的验证应当看脚本日志里每类分支的命中数量,而不是只看总量变化。
人工经验往往以“一般情况怎样、特殊情况怎样”的口语形式存在,转成脚本需求时需要压缩成可逐条核对的清单。每条清单包含:适用页面范围、触发条件、判定依据、脚本动作、跳过后的记录方式、人工接手出口。缺哪一项,就在该项旁边标注待确认,而不是用模糊表述填满。
交接时还要明确一个动作:脚本首次运行只记录不修改,输出每条例外的命中清单,由人工核对后再开启修改。这个动作的结果决定下一步——如果命中清单与预期一致,可以进入正式运行;如果出现描述里没覆盖的分支,说明例外清单还不完整,应先补充描述再继续,而不是边跑边改规则。
例外情况写得越具体,脚本能自动处理的比例反而越清晰。真正需要人工的页面会被单独列出来,而不是混在批量处理里被悄悄改错。