影刀RPA新手教程:数据校验与质量检查实战——采集完就知道数据是否准确
采集1000条数据,50条价格为空30条重复——不做校验等于白干
我第一次做完电商数据采集,信心满满把数据交给同事做分析,结果同事说——50条价格为空、30条重复数据、还有几条价格范围写反了(min比max还大)。数据质量一塌糊涂,分析结果全是垃圾。从那以后我养成了一个习惯:采集完必须跑校验,生成质量报告,有问题就告警。
数据校验不是可有可无的后处理,它是采集流程的必做步骤。校验四个维度——完整性、合法性、一致性、去重验证,每个维度都有具体可操作的检查方法。
安装与影刀环境
影刀安装走官网下载64位版本。数据校验主要用Python pandas,影刀内嵌Python环境,直接import pandas就行——不需要额外安装。但影刀的Python环境版本可能比较旧,如果pandas不可用,用影刀的【从文本中提取内容】指令做正则校验也能凑合。
影刀的Excel操作指令够用——【打开Excel】【读取数据表格内容】【写入Excel行】【筛选Excel】这些指令是校验流程的基础。
元素定位——校验流程也要抓元素
数据校验不是纯数据处理,有时候需要回到源网站验证数据准确性。比如怀疑某条价格数据不对,要回到电商页面重新抓取验证。
校验场景的元素定位和采集一样,四合一定位策略:
XPath定位——精确校验单个元素,比如某条商品的价格
CSS选择器——批量校验列表数据
正则匹配——从文本中提取数字做比对
捕获元素——快速验证单个页面
影刀的【获取元素文本】指令配合XPath,能快速抓取单个字段的值用于比对:
# 回源网站验证价格actual_price=browser.get_element('//span[contains(@class,"price")]',mode='xpath').get_text()影刀还提供了【从文本中提取内容】指令,内置多种正则提取模式——提取数字、提取手机号、提取Email、提取身份证号。做合法性校验时非常实用,不用写正则,选个模式就行。
自定义正则提取——当内置模式不够用时:
# 影刀的【从文本中提取内容】指令# 提取方式选"自定义内容",输入正则表达式# 提取价格范围的数字: r'(\d+)-(\d+)'# 提取日期: r'\d{4}-\d{2}-\d{2}'# 提取URL: r'https?://[\w./-]+'正则表达式在元素定位中也有用处——影刀的元素编辑支持正则匹配属性值。比如某个元素的class属性是"price_active_12abc",用正则^((?!disabled).)*$可以匹配不含disabled的所有class值。
变量与数据类型——校验结果的数据结构
校验结果用字典结构存储,包含四个维度的检测结果:
validation_result={'completeness':{# 完整性'empty_fields':{'price':50,'title':3,'url':0},'row_count':1000,'expected_rows':1000},'legality':{# 合法性'invalid_format':{'date':12,'phone':5},'invalid_range':{'price_below_zero':3,'price_above_max':0}},'consistency':{# 一致性'logic_conflict':{'min_gt_max':7,'start_after_end':0}},'deduplication':{# 去重'duplicate_count':30,'duplicate_ids':['id_123','id_456',...]},'total_issues':107,'quality_score':89.3# 100分满分}变量类型转换是校验的核心问题——采集数据全是文本类型,做数值校验前必须转换:
| 采集原始值 | 类型 | 校验需要类型 | 转换方法 |
|---|---|---|---|
| “15-25K” | str | int | 正则提取+int() |
| “2024-01-15” | str | datetime | datetime.strptime() |
| “99.5” | str | float | float() |
| “” | str | None | if not val: None |
| “NULL” | str | None | val.replace(‘NULL’, ‘’) |
踩坑点——float()转换"99.5元"会报错,因为"元"不是数字。先用正则提取纯数字部分再转换。
流程控制——校验流程的分支判断
数据校验流程用If条件判断做分支处理:
影刀的If指令支持多种条件:
- 文本包含/不包含
- 数字大于/小于/等于
- 变量为空/不为空
- 正则匹配/不匹配
校验流程的核心分支结构:
采集完成 → 读取Excel数据 → 完整性检查(空值判断) → 合法性检查(格式判断) → 一致性检查(逻辑判断) → 去重检查(ID重复判断) → 生成质量报告 → If判断: 问题率>10%? → 告警+暂停 → 正常+继续ForEach循环遍历每行数据做逐条校验:
# 逐行校验模板issues=[]foridx,rowinenumerate(data_rows):# 完整性:必填字段为空?ifnotrow.get('price')orrow['price']=='':issues.append({'row':idx+1,'field':'price','type':'empty'})# 合法性:价格是否是有效数字?try:price_val=float(re.sub(r'[^\d.]','',row['price']))ifprice_val<0:issues.append({'row':idx+1,'field':'price','type':'negative'})exceptValueError:issues.append({'row':idx+1,'field':'price','type':'invalid_format'})# 一致性:min_price <= max_price?ifrow.get('min_price')androw.get('max_price'):iffloat(row['min_price'])>float(row['max_price']):issues.append({'row':idx+1,'field':'price_range','type':'min_gt_max'})# 去重:ID是否重复?ifrow['id']inseen_ids:issues.append({'row':idx+1,'field':'id','type':'duplicate'})seen_ids.add(row['id'])While循环用于动态校验——一边采集一边校验,实时发现问题:
# 采集+校验并行流程whilehas_next_page:page_data=collect_page(browser)page_issues=validate_page(page_data)iflen(page_issues)>5:# 单页问题太多,可能页面有问题system.print_log('第{}页数据异常过多,暂停采集'.format(current_page))breakall_data.extend(page_data)all_issues.extend(page_issues)网页自动化——回源校验的完整操作
回源校验是指回到数据来源网站,重新抓取怀疑有问题的数据做比对。步骤:
从质量报告中提取有问题的数据ID列表
逐个打开对应的网页(用原始URL或搜索定位)
重新抓取该条数据
比对原始采集值和新抓取值
如果不一致,更新为新值
fromxbotimportweb,systemdefrevalidate_item(browser,original_url,original_data):"""回源验证单条数据"""browser.get(original_url)system.sleep(2)# 重新抓取各字段actual_title=browser.get_element('//h1[contains(@class,"product-name")]',mode='xpath').get_text()actual_price=browser.get_element('//span[contains(@class,"price")]',mode='xpath').get_text()# 比对differences={}ifactual_title!=original_data['title']:differences['title']={'original':original_data['title'],'actual':actual_title}ifactual_price!=original_data['price']:differences['price']={'original':original_data['price'],'actual':actual_price}returndifferences回源校验的成本比较高——1000条数据全部回源验证要花很长时间。建议只对问题数据做回源验证,没问题的不用重查。
数据处理——pandas批量校验最快
逐行用If判断做校验太慢,1000条数据要跑很久。用pandas批量校验,1秒出结果。
importpandasaspdimportnumpyasnpdefvalidate_with_pandas(file_path):"""pandas批量数据校验"""df=pd.read_excel(file_path)report={}# === 1. 完整性检查 ===# 必填字段为空的行数required_fields=['id','title','price','date']empty_counts={}forfieldinrequired_fields:# pandas判断空值:NaN、None、空字符串empty_mask=df[field].isna()|(df[field]=='')|(df[field]=='NULL')empty_counts[field]=int(empty_mask.sum())report['empty_fields']=empty_counts report['row_count']=len(df)# === 2. 合法性检查 ===# 价格是否是数字price_numeric=pd.to_numeric(df['price'].str.replace(r'[^\d.]','',regex=True),errors='coerce')invalid_price=price_numeric.isna().sum()# 价格范围检查negative_price=(price_numeric<0).sum()extreme_price=(price_numeric>999999).sum()# 日期格式检查date_parsed=pd.to_datetime(df['date'],errors='coerce')invalid_date=date_parsed.isna().sum()report['legality']={'invalid_price_format':int(invalid_price),'negative_price':int(negative_price),'extreme_price':int(extreme_price),'invalid_date_format':int(invalid_date)}# === 3. 一致性检查 ===# min_price > max_price 的逻辑冲突min_col=pd.to_numeric(df['min_price'],errors='coerce')max_col=pd.to_numeric(df['max_price'],errors='coerce')logic_conflict=(min_col>max_col).sum()report['consistency']={'min_gt_max':int(logic_conflict)}# === 4. 去重检查 ===duplicate_count=df.duplicated(subset='id',keep=False).sum()duplicate_ids=df[df.duplicated(subset='id',keep=False)]['id'].unique().tolist()report['deduplication']={'duplicate_count':int(duplicate_count),'duplicate_ids':duplicate_ids}# === 汇总 ===total_issues=sum(empty_counts.values())+int(invalid_price+negative_price+extreme_price+invalid_date+logic_conflict+duplicate_count)quality_score=round(100-(total_issues/len(df)*100),1)report['total_issues']=total_issues report['quality_score']=quality_scorereturnreportpandas校验比逐行If判断快50倍以上。1000条数据pandas处理不到1秒,逐行判断要50秒。这是数据校验的首选方式。
踩坑点——pandas的pd.to_numeric()加了errors='coerce’参数后,无法转换的值变成NaN而不是报错。这对校验来说刚好好用——NaN数量就是格式错误数量。
鼠标键盘图像自动化——校验流程的辅助操作
数据校验偶尔用到鼠标键盘操作,主要是两个场景:
- 截图保存问题数据——在源网页上截取有问题的数据区域,存为图片证据
- OCR识别图片中的数据——有些网站的价格是图片而非文字,用OCR提取做校验
截图保存——影刀的【截屏】指令截取指定窗口区域:
fromxbotimportsystem# 截取网页问题区域system.screenshot(region={'x':100,'y':200,'width':300,'height':150},save_path='D:/validation/screenshots/issue_row_{}.png'.format(row_idx))OCR校验——用影刀的百度OCR模块识别图片中的文字数据,和采集数据比对:
fromxbotimportai ocr=ai.baidu.BaiduAI(api_key='xxx',secret_key='xxx')ocr_result=ocr.ocr_from_file('D:/validation/screenshots/price.png')# ocr_result是字符串列表,拼接后和采集数据比对ocr_price=''.join(ocr_result)OCR在数据校验中不是最常用,但在特定场景(图片价格、图片验证码)很有用。了解就行,不是每条数据都要OCR。
键盘操作——Ctrl+F在网页上搜索特定ID做回源定位,比手动翻页快。
进阶技能——Python脚本+HTTP请求+正则校验
数据校验的进阶技能组合——Python脚本做批量校验+HTTP请求验证URL有效性+正则做格式校验。
URL有效性校验——采集的URL字段是否是可访问的网页:
fromxbotimportwebdefvalidate_urls(url_list,timeout=5):"""批量验证URL是否有效"""invalid_urls=[]forurlinurl_list:try:response=web.http_get(url,timeout=timeout)# 200-299状态码都是有效的ifresponse.status_code>=300:invalid_urls.append(url)exceptException:invalid_urls.append(url)returninvalid_urls正则校验大全——常用字段的正则表达式:
| 字段 | 正则 | 说明 |
|---|---|---|
| 手机号 | r’^1[3-9]\d{9}$’ | 1开头+3-9+9位数字 |
| r’1+@[\w.-]+.\w+$’ | 基本格式 | |
| 日期 | r’^\d{4}-\d{2}-\d{2}$’ | YYYY-MM-DD |
| 价格 | r’^\d+.?\d*$’ | 数字+可选小数 |
| URL | r’^https?😕/[\w./-]+$’ | http/https开头 |
| ID号 | r’^\d{6,20}$’ | 6-20位纯数字 |
影刀的【从文本中提取内容】指令封装了这些常用正则,不需要自己写。选择对应的提取方式就行——提取数字、提取手机号码、提取Email。
ADB是安卓端操作模块,数据校验不需要ADB。了解就行。
平台实战——电商+招聘双平台校验
数据校验在不同平台的侧重点不同:
| 维度 | 电商数据校验重点 | 招聘数据校验重点 |
|---|---|---|
| 完整性 | 价格为空、商品名为空 | 薪资为空、公司名为空 |
| 合法性 | 价格非数字、日期格式错 | 薪资格式错、经验年限异常 |
| 一致性 | min>max价格反了 | min_salary>max_salary |
| 去重 | 同一商品ID重复 | 同一职位ID重复 |
电商数据的常见问题:
- 价格为空——促销页价格藏在弹窗里,采集时没点到弹窗就空了
- 价格含单位——"99.5元"不是纯数字,校验时会报格式错误
- 日期格式混乱——有"2024-01-15"也有"01/15/2024"还有"20240115"
- 同一SKU重复——不同页码出现同一商品
招聘数据的常见问题:
- 薪资面议——没有数值,校验时标记为空
- 薪资格式不统一——“15-25K"和"15k-25k"和"15000-25000”
- 地点格式混乱——“北京·朝阳区"和"北京市朝阳区”
- 同一职位重复发布——同一公司同一职位在多天发布
双平台校验流程架构:
主流程 → 选择数据源(电商/招聘) → 读取Excel数据 → 平台特定校验(电商:价格校验 / 招聘:薪资校验) → 通用校验(完整性+合法性+一致性+去重) → 生成质量报告 → If判断: 问题率阈值 → 告警 / 继续系统联动——校验完自动告警+修复
校验结果出来后要做三件事——告警、修复、记录。
告警——问题率超过10%就发钉钉或邮件告警:
fromxbotimportmail issue_rate=report['total_issues']/report['row_count']*100ifissue_rate>10:mail.send(to='data_team@email.com',subject='数据质量告警: 问题率{}%'.format(round(issue_rate,1)),body='完整性问题: {}\n合法性问题: {}\n一致性问题: {}\n重复数据: {}'.format(report['empty_fields'],report['legality'],report['consistency'],report['deduplication']['duplicate_count']))修复——自动化修复常见数据问题:
| 问题 | 自动修复方式 |
|---|---|
| 价格为空 | 回源网站重新抓取 |
| 价格含单位 | 正则提取纯数字 |
| 日期格式不统一 | datetime.strptime统一格式 |
| min>max | 交换min和max |
| 重复数据 | pandas.drop_duplicates()按ID去重 |
| "NULL"字符串 | 替换为None或空 |
# 自动修复模板defauto_fix(df):"""自动修复常见数据问题"""# 价格去单位df['price']=df['price'].str.replace(r'[^\d.]','',regex=True)df['price']=pd.to_numeric(df['price'],errors='coerce')# 日期格式统一df['date']=pd.to_datetime(df['date'],errors='coerce').dt.strftime('%Y-%m-%d')# min>max交换swap_mask=df['min_price']>df['max_price']df.loc[swap_mask,['min_price','max_price']]=df.loc[swap_mask,['max_price','min_price']].values# 去重df=df.drop_duplicates(subset='id',keep='first')returndf质量报告写入——用影刀的Excel指令把报告写入独立文件:
fromxbotimportexcel# 创建质量报告Excelreport_wb=excel.create('D:/validation/quality_report.xlsx')report_wb.write_row(1,['检查维度','问题类型','问题数量','问题详情'])report_wb.write_row(2,['完整性','价格为空',50,'行3,行7,行15,...'])report_wb.write_row(3,['合法性','价格格式错',12,'行5,行9,...'])report_wb.save()工程化与规范——校验流程标准化
数据校验是每个采集项目的必做步骤,标准化后能直接复用:
- 校验规则配置化——每个项目的校验规则放在validate_config.json里
- 校验脚本模块化——完整性、合法性、一致性、去重各封装成子流程
- 报告格式统一——所有项目使用相同的质量报告模板
- 告警阈值可配置——不同项目的问题率阈值不同
# 校验配置文件结构config={'project':'ecommerce_price','required_fields':['id','title','price','date'],'numeric_fields':['price','min_price','max_price'],'date_fields':['date'],'unique_fields':['id'],'alert_threshold':10,# 问题率超过10%告警'auto_fix':True# 是否自动修复}命名规范——校验文件用"validate_项目名.json"格式,质量报告用"report_项目名_日期.xlsx"格式。
更详细的校验规则配置和自动化修复方案,可以参考 home.linyan.cloud 上分享的数据质量检查工具源码。
速查表与常见报错
| 报错 | 原因 | 解决 |
|---|---|---|
| pd.read_excel()报错 | 文件不存在或格式错 | 确认路径+用openpyxl引擎 |
| pd.to_numeric()全变NaN | 原始数据有文字混入 | 先用str.replace清理再转换 |
| 正则提取返回空列表 | 匹配模式不对 | 用影刀的【从文本中提取内容】测试正则 |
| 校验结果全是0 | 字段名和实际列名不一致 | 先用df.columns确认列名 |
| 去重后数据量不对 | keep参数选错 | keep='first’保留第一条,keep=False全删 |
| 质量分数为负数 | 问题数>数据行数 | 检查是否有重复统计 |
关键速查:
- 完整性:df[field].isna() | (df[field] == ‘’)
- 合法性:pd.to_numeric(df[field], errors=‘coerce’).isna()
- 一致性:(df[‘min’] > df[‘max’]).sum()
- 去重:df.duplicated(subset=‘id’, keep=False).sum()
- 自动修复:df.drop_duplicates(subset=‘id’, keep=‘first’)
- 价格清理:df[‘price’].str.replace(r’[^\d.]', ‘’, regex=True)
- 告警判断:issue_rate = total_issues / row_count * 100
- 正则提取:影刀【从文本中提取内容】指令
采集1000条数据,自动跑校验,发现50条价格为空30条重复,生成质量报告89.3分。校验流程标准化后,每个新项目只需要改配置文件,不用重写校验逻辑。
#影刀RPA #新手教程 #数据校验 #质量检查 #pandas #数据清洗 #自动化修复
作者:林焱
\w.- ↩︎