直接回答:不要只写“遇到异常就跳过”,而要把例外拆成三件事——触发条件、判定依据、处理动作,并明确例外发生后脚本应该继续、暂停还是交回人工。对已有经验的站长来说,真正让脚本跑偏的往往不是主流程,而是那些人工操作时凭直觉处理、写需求时却没说清的边界。
假设你有一批页面,人工检查时会看标题是否为空、正文是否过短、内链是否指向已删除地址。你打算把这三步写成脚本,让程序每天跑一次并输出待处理清单。常规做法是:标题为空就标记,正文少于某个长度就标记,内链返回错误就标记。但真正跑起来后,你会遇到人工操作时不会当成问题的情况,例如标题为空但页面本身是分类聚合页,正文短但页面是联系方式页,内链返回错误但目标地址只是临时不可访问。这些就是例外情况。
如果需求里只写“异常跳过”,脚本作者只能自己猜:是整页跳过,还是只跳过这一项检查?跳过之后要不要记录?下次还查不查?结果就是脚本能跑,但输出清单和人工判断不一致,你还是要重新翻一遍。
人工经验里常说“这种页面不用管”,但脚本需要知道“这种”指什么。描述例外时,先把触发条件写成脚本能判断的字段或状态,而不是感受。
这里的关键不是一次写全,而是让每个例外都能对应到一个可观察的条件。假设你写“聚合页不检查正文长度”,脚本作者就需要追问:聚合页怎么识别?如果识别不了,这条例外就无法执行。
触发条件只说明“什么时候算例外”,处理动作才决定脚本下一步怎么走。常见动作可以分成四类,写需求时要明确选哪一种。
动作不同,后续影响也不同。选“跳过当前检查”,你的待处理清单会变短,但其他检查仍然有效;选“跳过整个页面”,清单更短,但你可能失去该页面其他问题的线索;选“待人工确认”,清单不会自动变短,但你能保留判断权。写需求时要把这个取舍说清楚,而不是只写“异常处理”。
假设你写了一条需求:“内链返回错误时,如果是临时不可访问,就跳过。”这句话对脚本来说仍然模糊。可以改成:
当内链目标返回错误状态,且同一目标在最近一次检查中也返回错误时,标记为待人工确认;如果只是本次返回错误,记录但不标记。
这个例子里,触发条件是“返回错误状态”加“最近一次也错误”,处理动作是“待人工确认”或“只记录”。它没有承诺一定正确,但至少让脚本作者知道该怎么写判断分支。你也可以把“最近一次”换成“连续两次”或“同一天内两次”,关键是选一个可执行的口径,而不是写“临时”。
验证方法很简单:拿三到五个已知页面,人工先判断哪些应该被当成例外,再让脚本按需求跑一遍,对比结果。如果差异集中在某一条描述上,就回去改那条,而不是改整个脚本。这个动作的结果会直接影响下一步:差异收敛后,你才适合扩大运行范围;差异仍然分散,说明例外描述还没到可交付的程度。
第一个是例外之间的优先级。假设一个页面同时满足“标题为空”和“属于免检栏目”,脚本应该先判断哪一个?如果免检优先,标题为空就不会被标记;如果标题检查优先,免检就失效。写需求时要说明顺序,否则不同人实现会得到不同结果。
第二个是例外清单的维护方式。例外条件写进脚本后,谁来更新?是每次发现新情况就改代码,还是把例外整理成一份可配置清单,让脚本读取?前者改动慢但集中,后者灵活但需要额外维护。选择哪一种,取决于例外出现的频率和你能接受的维护成本。如果例外很少且稳定,写进脚本更简单;如果例外经常增加,单独维护清单更合适。
最后要提醒的是,比较脚本运行前后的结果时,不要把差异全部归因于例外处理。搜索需求变化、页面本身更新、数据采集时间不同,都可能让清单看起来变长或变短。一次改动不能单独证明例外描述正确,需要结合多次运行和人工抽查来判断。把例外写成可判定的条件、明确的动作和可验证的例子,脚本才更接近你原本的人工经验。