HTTP 200 和类型正确的记录,仍可能不应触发业务动作。选择器可能从目标价格移到相邻价格;来源也可能已发生正常业务变化,而旧基线仍被沿用。对于获准使用代理的采集工作流,应把这类情况视为数据质量异常:在记录进入提醒、导出或决策前隔离,保留证据,并通过受控的解析器变更恢复。
1. 围绕业务动作定义字段契约
先定义一条记录可能触发的最小动作,例如一个市场中的获准商品可售提醒。列出字段、类型、是否必需、是否可为 null、零是否有业务含义,以及信任该字段需要的来源证据。“可选”表示可以不出现;“可空”表示出现时可为 null。两者都不意味着缺失的必需字段可以填成零。
| 字段 | 契约 | 业务动作规则 |
|---|---|---|
sample_key | 本次采集记录的必需唯一键 | 用于汇总同一运行的字段决定;不能把它当作来源身份。 |
record_id | 必需的非空来源身份 | 在同一来源、市场和观察时间窗内缺失或重复即隔离。 |
price_minor | 必需整数;仅当来源明确表示免费时允许 0 | 不能用真值判断:零是值,缺失不是。 |
currency | 必需,且为获准币种代码 | 未知或与价格不匹配即隔离。 |
availability | 可选且可空;缺失或为 null 时记为 UNKNOWN | UNKNOWN 不等于“有货”;不得触发依赖可售状态的动作。 |
source_updated_at | 来源发布时必需;否则可缺省 | 已发布但为 null 或缺失时记为 UNKNOWN,不可用采集时间代替。 |
JSON Schema 的 object 参考说明:属性默认不是必需字段,额外属性默认允许;需要的限制必须明确写出。必需字段仍可能为 null,除非模式禁止。本文借用这些概念建立工作流契约,不是完整 JSON Schema 实现。
2. 把采集时间与来源时间分开
记录工作流收到响应的 retrieved_at,以及获准来源 URL 或脱敏定位符、响应指纹、解析器版本和契约版本。仅在来源提供且含义已记录时才写 source_updated_at。刚刚采集不等于来源数据新;未变化的值也可能仍是当前值。拿不到来源时间时写 UNKNOWN,凡是依赖新鲜度期限的动作一律暂停。
按本团队保留政策,保存原始响应或受控访问的脱敏引用足够久,以便重现争议提取。普通告警日志不要写入凭据、Cookie、个人数据或受保护的页面内容。
3. 让每条记录进入接收、隔离、暂停或停止
校验是在业务动作之前的门槛,不是来源陈述真实的证明。值类型正确,也可能来自错误元素。将同一 sample_key 的所有字段校验汇总为一个行状态:只有全部必需字段、来源证据核验和所需的新鲜度核验均通过,才是 ACCEPT_NEXT_STAGE;缺失证据记为 UNKNOWN,对应记录进入 HOLD。优先级依次为 STOP(访问限制)、QUARANTINE(已知无效或不匹配记录)、HOLD。业务动作状态只可为 NOT_SENT、HELD、BLOCKED、SENT_AFTER_APPROVAL 或 UNKNOWN。下表是虚构记录 ID 和结果的教学例子,不是 IPHTML 测量或完整校验器。
| 假设观察 | 决定 | 证据与下一步 |
|---|---|---|
price_minor=0,有来源明确的免费状态、必需字段和来源定位符 | 进入下一校验阶段 | 保留证据;零不是缺失。是否发免费提醒仍由语义规则决定。 |
price_minor 缺失 | 隔离 | 不能默认填零;保留字段错误和解析/来源证据。 |
契约要求整数,但 price_minor="999" | 隔离 | 记录类型漂移;除非经过审核的契约修订允许,否则不可静默转换。 |
| 已提取整数价格,但保存的定位符指向推荐商品卡 | 隔离 | 类型校验通过,但来源到字段的证据失败;审核选择器和页面证据。 |
source_updated_at=UNKNOWN,且提醒有新鲜度期限 | 暂停 | 单独保存该记录;采集时间不能满足该期限。 |
| 403、429 或访问限制 | 停止受限请求路径 | 采用来源支持的访问方式或权限流程,不能通过轮换出口绕过。 |
Scrapy 说明 item pipeline 可以校验条目并丢弃条目,使其不再进入后续组件。这支持隔离阶段,但不代表其示例足以构成字段契约:其价格示例使用真值判断,会把 0 当作缺失。必须为自身领域显式规定零和空值规则。参见 Scrapy Item Pipeline 文档。
4. 离线复现“字段看似正确却取错”的情况
以下是完全虚构的测试样例,不访问网络,也不抓取真实网站。两个数都是整数,因此当提取路径从目标报价漂到推荐商品卡时,类型校验仍会通过。片段和输出可供人工复核语义证据为何失败。
<div id="target" data-price-minor="1299">目标报价</div>
<aside class="recommended" data-price-minor="999">推荐商品</aside>
预期定位符:#target[data-price-minor] → {"price_minor": 1299}
漂移定位符:.recommended[data-price-minor] → {"price_minor": 999}
两个输出:整数类型通过
漂移输出:来源定位符和标签不匹配 → 隔离
记录选择器或提取路径、来源片段或获批脱敏证据、解析器版本和契约版本。契约校验通过不等于提取的来源陈述真实,也不等于语义正确。
5. 依赖来源证据定位漂移,而非只看状态码
每个隔离记录都应留下契约字段名、原因、来源定位符、采集时间、解析器和契约版本,以及脱敏响应指纹。将目标字段附近的标签、单位、币种和稳定页面上下文与捕获证据对照,可区分缺失标记、类型变化、来源层变化,以及选择器仍返回合理数值却选错元素的情况。
一条公开的 r/webscraping 问题询问:选择器或布局变化后,采集器继续返回记录怎么办;其中还涉及类型正确但含义错误的值,以及谁应更新正常业务变化后的基线。它只证明这个问题被提出;评论、数量和建议都不是本工作流的事实依据。
6. 每次只恢复一项契约变更
- 冻结受影响的下游动作,圈定解析器版本、来源和采集时间窗。页面契约变化不等于代理事故,也不必把每条字段错误都称为事故。
- 提出一项解析器或契约修订,写明理由、经审核的来源样本和负责人。来源的正常业务变化需要新基线;把旧基线复制过去不算批准。
- 让少量获准的试运行样本经过新版本,同时保留旧版本结果和证据。审核字段与来源的对应、空/零处理和新鲜度限制。
- 批准或拒绝修订,并记录契约版本。仅修复解析器不能放行处于 HOLD 的记录:每条记录仍须满足自身的来源证据、新鲜度条件和权限规则。只按批准范围重新处理仍满足这些条件的待审记录。
工作结果分母和状态请使用稳定性评分卡;需要更广泛的生产事故指挥和分阶段恢复时使用事故处置手册。本文负责的是技术响应成功后的记录级业务动作门槛。
7. 扩大前先用空白契约工作表
下载双语字段契约工作表。它给出字段定义,并保留实际运行证据列为空。示例规则须先按具体任务修订并获批准,再作为字段契约使用。每个来源和契约版本复制一份,不能覆盖此前已批准的基线;表中预留实际观察值或 UNKNOWN、负责人、审核人、审核时间和批准/基线证据。缺失的运行证据保持 UNKNOWN;即使 HTTP 请求成功,被隔离的行也不能进入业务动作队列。
若 API、许可数据源或直接的获准访问已经满足该动作的证据和新鲜度要求,就保留更简单的路径。若获准工作流可能需要轮换路径,可查看轮换代理,并通过联系团队说明脱敏的来源类别、获准市场、契约字段和隔离要求。改变路径前确认当前适用性、权限和限制。本文不承诺 IPHTML 的数据质量、可用性或恢复时间。
资料核对日期为 2026 年 10 月 22 日:JSON Schema object 参考、Scrapy Item Pipeline 文档及链接的公开问题。字段契约、决定和例子均为编辑教学材料。