4. 数据源接入与清洗:内部数据与外部数据的 ETL 实践
贷后预警模型的准确性高度依赖数据质量。本章聚焦于多源异构数据的接入策略与 ETL(Extract, Transform, Load)清洗流程,确保进入预警看板的数据具备一致性、完整性和时效性。
4.1 数据源分类与接入策略
贷后预警所需数据可分为内部与外部两大类,接入方式与更新频率差异显著:
| 数据类别 | 典型数据源 | 接入方式 | 更新频率 | 关键字段示例 |
|---|---|---|---|---|
| 内部-还款流水 | 核心账务系统、还款渠道 | CDC(变更数据捕获)/ 批量接口 | T+0 实时 / 每日 | 借据号、应还日、实还日、逾期天数、本金余额 |
| 内部-行为数据 | APP 埋点、客服系统、交易日志 | 消息队列(Kafka)/ 日志采集 | 准实时 / 每小时 | 登录频次、设备变更、客服投诉次数、大额交易标记 |
| 外部-征信 | 人行征信、百行征信、朴道征信 | API 查询 / FTP 文件 | 按需 / 每周 | 信贷记录、查询次数、逾期标识、担保余额 |
| 外部-工商司法 | 国家企业信用信息公示系统、裁判文书网 | API 接口 / 爬虫(合规授权) | 每日 / 每周 | 经营状态、行政处罚、被执行人、开庭公告 |
| 外部-黑名单 | 行业共享黑名单、反欺诈联盟 | API 实时查询 / 离线文件 | 实时 / 每日 | 身份证号、手机号、设备指纹、命中规则 |
接入原则:内部高频数据优先采用 CDC + 消息队列实现准实时接入;外部低频数据(如工商、司法)采用每日批量调度,避免对源系统造成过大压力。
4.2 ETL 清洗核心流程
原始数据无法直接用于预警模型,必须经过标准化清洗。以下为贷后场景下的 ETL 关键步骤:
- 抽取(Extract): 按时间戳或增量标记拉取数据,避免全量重复抽取。还款流水按“最后修改时间”增量抽取;征信报告按“查询日期”增量抽取。
- 转换(Transform):
- 字段标准化: 统一日期格式(YYYY-MM-DD)、金额单位(分转元)、枚举值映射(如“逾期1-30天”转为逾期天数数值)。
- 衍生计算: 计算“距还款日天数”、“连续逾期次数”、“近30天查询征信次数”等预警特征。
- 数据脱敏: 对身份证号、手机号等敏感字段进行 MD5 或 AES 加密,仅保留业务需要的脱敏标识。
- 加载(Load): 将清洗后的数据写入预警数据仓库(DWD 层),按客户 ID 和借据号建立宽表,供模型实时调用。
清洗规则示例(还款流水):
- 过滤掉测试借据(借据号以 'TEST' 开头)。
- 将“实还日期”为 NULL 且“应还日期”早于当前日期的记录标记为“逾期”。
- 逾期天数 = 当前日期 - 应还日期(若实还日期不为空,则取实还日期 - 应还日期)。
- 过滤掉测试借据(借据号以 'TEST' 开头)。
- 将“实还日期”为 NULL 且“应还日期”早于当前日期的记录标记为“逾期”。
- 逾期天数 = 当前日期 - 应还日期(若实还日期不为空,则取实还日期 - 应还日期)。
4.3 数据质量监控与异常处理
ETL 过程中必须嵌入质量监控规则,防止脏数据污染预警模型:
| 监控维度 | 规则描述 | 告警阈值 | 处理动作 |
|---|---|---|---|
| 完整性 | 关键字段(借据号、客户ID、应还日)不可为空 | 空值率 > 0.5% | 阻断该批次加载,通知数据运维 |
| 一致性 | 同一借据在还款流水与核心系统余额一致 | 差异笔数 > 10 | 标记异常借据,人工复核 |
| 时效性 | 还款流水数据延迟不超过 30 分钟 | 延迟 > 30 分钟 | 触发 Kafka 消费积压告警 |
| 准确性 | 逾期天数计算值与业务系统一致 | 偏差 > 1 天 | 回刷历史数据,修复计算逻辑 |
避坑提示: 外部征信数据常存在“多头借贷”字段缺失或格式不统一的问题。建议在 ETL 中建立“征信字段映射表”,将不同征信机构的字段名统一映射到标准字段,避免模型训练时出现特征断裂。
4.4 数据接入与清洗架构总览
以下 SVG 图展示了从多源数据接入到清洗加载的完整链路,以及各环节的监控反馈机制:
4.5 实战:还款流水 ETL 清洗代码示例
以下为使用 PySpark 对还款流水进行清洗的典型代码片段,包含字段标准化、逾期标记和空值处理:
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, when, datediff, current_date, to_date
spark = SparkSession.builder.appName("repayment_etl").getOrCreate()
# 读取原始还款流水
df_raw = spark.read.parquet("hdfs://data/repayment_raw/")
# 清洗逻辑
df_clean = df_raw \
.filter(col("借据号").isNotNull()) \
.filter(~col("借据号").startswith("TEST")) \
.withColumn("应还日期", to_date(col("应还日期"), "yyyyMMdd")) \
.withColumn("实还日期", to_date(col("实还日期"), "yyyyMMdd")) \
.withColumn("逾期天数",
when(col("实还日期").isNull(),
datediff(current_date(), col("应还日期"))
).otherwise(
when(col("实还日期") > col("应还日期"),
datediff(col("实还日期"), col("应还日期"))
).otherwise(0)
)
) \
.withColumn("逾期标记",
when(col("逾期天数") > 0, 1).otherwise(0)
) \
.withColumn("数据日期", current_date())
# 写入预警宽表
df_clean.write.mode("overwrite").parquet("hdfs://data/dwd/repayment_clean/")
print("ETL 清洗完成,共处理 {} 条记录".format(df_clean.count()))
关键说明:
- 使用
- 逾期天数计算区分“已还清”与“未还清”两种场景,避免负值。
- 写入时采用
- 使用
filter 剔除测试数据与空值借据,保证主键完整性。- 逾期天数计算区分“已还清”与“未还清”两种场景,避免负值。
- 写入时采用
overwrite 模式,配合分区字段(如数据日期)实现增量覆盖。
4.6 数据接入清洗清单(Checklist)
在搭建贷后预警看板前,建议按以下清单逐项确认数据就绪状态:
- ✅ 内部还款流水: 已接入至少 12 个月历史数据,包含借据状态变更记录。
- ✅ 内部行为数据: 已接入客户 APP 登录、设备变更、客服交互等行为日志。
- ✅ 外部征信数据: 已建立征信查询授权机制,字段映射表已完成。
- ✅ 工商司法数据: 已配置每日增量更新任务,覆盖被执行人、行政处罚等关键事件。
- ✅ 黑名单数据: 已对接至少 2 家行业反欺诈数据源,支持实时查询。
- ✅ 质量监控: 已配置完整性、一致性、时效性告警规则,并设置通知渠道。
进阶建议: 对于外部数据(如征信、工商),建议建立“数据快照表”,每日保留全量快照,便于回溯历史状态变化,支撑贷后预警模型的时序特征计算。