- 自动会话管理
- 锁定 195 个国家/地区的任意城市
- 无限并发会话
数据验证
简而言之:数据验证会根据预期的类型、格式、范围和完整性规则检查采集到的记录,从而在损坏的数据进入任何依赖它的系统之前将其发现。
数据验证是数据采集与使用之间的质量关卡。在网页数据管道中,它比在大多数系统中更加重要,因为数据源不受你控制,并且可能在毫无预警的情况下发生变化。网站重新设计不会产生错误,而是会生成一些结构看似正常、实际上却不包含任何有用信息的记录。
验证层级:
- 字段级:每个值的类型、格式和范围是否正确?价格应为正数,货币应使用有效的 ISO 代码。
- 记录级:各字段之间是否一致?高于标价的促销价单独来看有效,但组合起来却是错误的。
- 批次级:本次运行结果是否与之前的运行结果相似?记录数量突然下降或空值激增都表明存在问题,无论单条记录是否通过验证。
- 跨数据源:不同的独立数据源是否一致?如果某件商品在四个网站上的价格都是 40,而在第五个网站上是 4,这更可能是解析错误,而不是捡到了便宜货。
常见验证规则:
| 字段 | 规则 | 通常可发现的故障 |
|---|---|---|
| price | 正数,且低于合理上限 | 货币符号被解析为数字的一部分 |
| currency | 三个字母,且为有效的 ISO 4217 代码 | 区域设置检测失败 |
| url | 绝对 URL,使用 HTTP 或 HTTPS 协议 | 相对链接未解析 |
| title | 非空,长度在限制范围内 | 选择器匹配到了空容器 |
| rating | 介于 0 和评分上限之间 | 抓取到了百分比而不是星级评分 |
| scraped_at | 时间较近,且不能是未来时间 | 时区处理错误 |
实施字段验证:
from datetime import datetime, timezone
VALID_CURRENCIES = {"USD", "EUR", "GBP", "JPY", "ILS"}
def validate(record):
errors = []
title = record.get("title")
if not title or not title.strip():
errors.append("title_empty")
price = record.get("price")
if price is None:
errors.append("price_missing")
elif not isinstance(price, (int, float)):
errors.append("price_not_numeric")
elif price <= 0 or price > 1000000:
errors.append("price_out_of_range")
currency = record.get("currency")
if currency not in VALID_CURRENCIES:
errors.append("currency_invalid")
url = record.get("url", "")
if not url.startswith(("http://", "https://")):
errors.append("url_not_absolute")
ts = record.get("scraped_at")
if ts and ts > datetime.now(timezone.utc):
errors.append("timestamp_future")
return errors
收集所有错误,而不是在遇到第一个错误时就返回,这一点非常重要。知道一条记录违反了四项规则,比只知道它违反了一项规则更有助于诊断,而且还能避免“修复一个、重新运行、再发现下一个”的循环。
批次验证可以发现记录验证遗漏的问题:
破坏性最大的故障,是那些每条记录单独看都有效的故障。
如果某个选择器失效,并在每个页面上都为价格返回 null,那么允许价格为 null 的 schema 会让每条记录都通过验证。系统不会抛出任何错误,只是数据集中最重要的那一列变成了空列,而问题要到几天后生成报告时才会暴露。
批次检查通过将本次运行与历史运行进行比较,而不是仅与规则进行比较,来发现这类问题。有效的信号包括与上一次运行相比的记录数量、每个字段的空值率、值的分布,以及发生变化的记录比例。某个字段的空值率从 2% 上升到 97%,显然意味着存在问题,而任何单条记录规则都无法将其标记出来。
决定如何处理验证失败:
只有在验证失败会触发明确操作时,验证才有用,而正确的操作会因严重程度而异。
拒绝记录。适用于必填字段不可用的情况。记录会被隔离而不是删除,以便后续检查和重新处理。
接受并添加标记。适用于可选字段验证失败的情况。记录会与质量标记一起存储,以便下游使用者在需要时进行筛选。
修复。适用于确定性的修复,例如删除多余空格或统一大小写。修复过程绝不能猜测缺失值。
停止处理该批次。适用于批次级检查失败的情况。发布一个 97% 的价格都为 null 的批次,比完全不发布更加糟糕。
验证与信任:
数据集的价值取决于使用者是否信任它。一份基于错误解析结果生成的定价报告,造成的长期损害比缺失一天的数据更严重,因为它会改变人们对之后每一份报告的看法。
因此,验证应在数据管道内部进行,而不是放在分析层。等到分析师发现结果看起来不对时,错误数据早已被查询、制成图表并加以引用。
Bright Data 的数据集和网页抓取工具 API会在交付前执行验证,因此收到的记录已经过完整性和类型一致性检查,无需在接收后再增加验证层。