Migrate CMB  ·  China Merchants Bank Statement Pipeline

从一封邮件,
到一张可信的账单

招商银行「每日信用管家」邮件经本机 Python 工具链解析、分类、幂等入库,落入腾讯云 CloudBase 内网 MySQL, 再聚合为看板与月报。全程数据不外发,SQL 只走 tcb 代理。

已核对 · RECONCILED
对账单摘要 / SUMMARY截至 2026-07-30
交易明细0
CNY 正向消费总额¥0
活跃消费天数0
数据表 · 自动化任务4 · 3
01

架构总览

四条横向轨道:顶部控制 / 代理,中部数据主路,底部交付总线。悬停任意组件查看职责并高亮其数据通路。

采集 解析 · SQL · 执行 写入存储 只读查询 快照交付 控制(虚线)
控制 / 代理轨 WorkBuddy 调度 automation · 每日08:00 / 每月1日09:00 / 手动 tcb CLI 代理 db execute · hosting deploy 外部数据源 163 网易邮箱 IMAP / SSL :993 发件域 cmbchina.com 账单邮件类型 ▸ 每日信用管家 ▸ e招贷账单 ▸ 消费信贷·汽车分期 本地 macOS · WorkBuddy 执行 采集 · fetch_emails() imap.bundle.js(netease-mail 连接器) --recent N 天窗口 · 只读拉取 解析 & SQL 生成 cmb_common · ingest_bills / ingest_installments 正则抽取 → classify 分类 → dedup_key 幂等 → INSERT … ON DUPLICATE KEY UPDATE 执行 · run_sql.py 安全闸:拒绝 DROP / DELETE / TRUNCATE 逐条经 tcb 代理执行 · 支持断点续跑 聚合 & 产出 gen_dashboard_data → dashboard-data.json gen_bill_report → 月度 Markdown 报告 verify_db → 三方对账(邮件·CSV·DB) 随附资产 merchant_map.json · FX 近似汇率 · CATEGORY_RULES 腾讯云 CloudBase MySQL · TDSQL-C raw_bill_email bill_transaction bill_daily bill_installment 仅 VPC 内网 172.17.0.11:3306 utf8mb4 / InnoDB · 不可直连 ⚠ 本机/浏览器均无法直连 静态托管 · dist/ index.html + dashboard-data.json 消费端 浏览器看板 Chart.js 实时聚合 账单月 / 自然月筛选 Obsidian 月报 分类 / 趋势 / Top 商户 iCloud 同步 Markdown 提醒 & 核对 Apple Notes · 大额/异常 verify_db 周期对账 交付轨 · 本机聚合快照 → tcb hosting deploy → 静态托管(非实时,刷新重算) SQL 经代理 read-only 聚合
组件详情
悬停任意组件
鼠标移入架构图中的任一节点,可高亮其上下游数据通路并在此查看职责说明。
02

数据流 · 端到端增量管道

一条交易从招行邮件到看板的完整旅程。悬停任一环节展开其函数、正则与产物。

1触发调度
WorkBuddy automation 每日 08:00 调起入库脚本;月度报告每月 1 日 09:00;看板刷新可手动触发。
ingest_bills.pyingest_installments.py--from-csv 历史回填
三条自动化:DAILY 08:00 增量入库 · MONTHLY 1日 09:00 月报 · MANUAL 看板刷新
2拉取邮件采集
fetch_emails() 调用 imap.bundle.js 经 IMAP/SSL :993 按 --recent N 天窗口只读拉取 163 邮箱。
cmb_common.fetch_emails产出 · emails[]
凭证由 netease-mail 连接器注入(NETEASE_EMAIL_USER/PASS),不落盘、不进 git
3筛选招行邮件采集
按发件域 cmbchina.com + 主题关键字过滤:「每日信用管家」走消费明细,「e招贷 / 消费信贷」走分期。
filter_cmbfilter_installment产出 · 命中邮件
主题键:SUBJECT_KEY="每日信用管家" · INSTALLMENT_SUBJECT_KEYS=("e招贷","消费信贷")
4解析正文转换
html_to_text 压平标签后,正则抽取交易行(时间/币种/金额/尾号/商户)与分期明细(本金/利息/期数)。
parse_email_textparse_installment_email产出 · rows[] / items[]
核心正则 TXN_RE:时间 + (CNY|USD|EUR) + 金额 + 尾号 + 商户;账单日由 DATE_RE 「您的消费明细如下」锚定
5分类 & 幂等 & 折算转换
classify() 按 merchant_map 精确映射 → 关键词规则给类别/渠道;dedup_key = md5(7字段);外币按近似汇率折算 amount_cny。
classifydedup_keyFX_RATES产出 · 标准化行
幂等键:md5(bill_date|time|cur|card|type|amount|merchant);汇率 USD=7.2 · EUR=7.8 · CNY=1
6生成幂等 SQL转换
批量生成 INSERT … ON DUPLICATE KEY UPDATE(交易/日汇总/原始邮件/分期),写入 statements JSON 文件,不进对话上下文。
txn_insert_sqldaily_rollup_sqlraw_email_sql产出 · statements JSON
日汇总用 GROUP BY bill_date + ODKU 重算,天然保证 total = Σ 明细
7执行入库写入
run_sql.py 校验安全闸(拒绝 DROP/DELETE/TRUNCATE/GRANT)后,逐条经 tcb db execute 代理写入内网 MySQL,失败可断点续跑。
run_sql.pytcb db execute产出 · 4 张表落库
MySQL 仅 VPC 内网,pymysql 直连不可行,tcb CLI 是唯一执行通道
8聚合产出只读
gen_dashboard_data 拉全量交易行输出 dashboard-data.json;gen_bill_report 多维聚合生成月度 Markdown。
gen_dashboard_data.pygen_bill_report.py产出 · JSON / Markdown
口径:amount_cny > 0 正向消费;前端按账单月/自然月/卡号实时重聚合
9发布交付交付
tcb hosting deploy 把 dist/ 推上 CloudBase 静态托管;月报写入 Obsidian(iCloud 同步)。数据新鲜度靠刷新动作。
tcb hosting deploy产出 · 线上看板 / 月报
看板模式 = 本机聚合快照 → 静态托管(浏览器/云函数无法直连该 MySQL)
10消费 & 核对交付
浏览器看板 / Obsidian 月报 / Apple Notes 提醒;verify_db.py 以原始邮件 + 历史 CSV 双重比对 DB,确保金额零差异。
verify_db.py产出 · 核账报告
最近一次核对:CSV 2303/2303 匹配 · 原始邮件 56/56 匹配 · 0 金额差异
03

数据模型 · 4 张表

横向滚动查看全部表结构。幂等键(UK)是重复执行不产生脏数据的保障。

bill_transaction 核心
信用卡交易明细
idBIGINTPK
bill_dateDATEIDX
txn_timeDATETIME
merchantVARCHAR(255)
amountDECIMAL(12,2)
currencyVARCHAR(8)
card_noVARCHAR(16)
category / channelVARCHAR
fx_rateDECIMAL运行时+
amount_cnyDECIMAL(12,2)运行时+
dedup_keyVARCHAR(191)UK
负数 = 退款/冲正 · 复合索引 (bill_date, category)
raw_bill_email
每日信用管家原始邮件快照
idBIGINTPK
mail_uidVARCHAR(191)UK
sender / subjectVARCHAR
received_atDATETIME
body_textLONGTEXT
parsed_jsonJSON
statusTINYINT
status:0 未解析 / 1 已解析 / 2 失败 — 供事后追溯重解析
bill_daily
每日账单汇总
idBIGINTPK
bill_dateDATEUK
due_amountDECIMAL(12,2)
min_paymentDECIMAL(12,2)
total_amountDECIMAL(12,2)
txn_countINT
由明细 GROUP BY 重算 · total = Σ(amount_cny>0)
bill_installment
分期还款明细(e招贷 / 汽车分期)
idBIGINTPK
account_typeVARCHAR(32)
productVARCHAR(128)
item_type本金 / 分期利息
cur_no / total_noINT
amount / due_amountDECIMAL
original_amountDECIMAL(14,2)
due_dateDATEIDX
dedup_keyVARCHAR(191)UK
幂等键 = md5(product|item_type|cur_no|total_no)
04

口径与约束

这些规则写进代码、也写进看板与报告——是数字可信的前提。

统计口径
总额只算 CNY 正向消费
amount_cny > 0 计总额;退款(负数)与外币单独列示、不冲抵总额。消费笔数与全部明细行数刻意区分。
外币折算
近似常量汇率
USD=7.2 · EUR=7.8 · CNY=1 写入 fx_rate / amount_cny(用户已确认)。如需严格当日汇率,应改为按交易日查历史汇率表。
幂等
重复执行零脏数据
交易 dedup_key=md5(7字段);分期按 product|item_type|cur_no|total_no。全部 INSERT 带 ON DUPLICATE KEY UPDATE。
安全闸
只写不删
run_sql.py 拒绝 DROP / DELETE / TRUNCATE / GRANT;查询走 --read-only。Agent 仅插入与查询。
网络边界
MySQL 仅 VPC 内网
本机与浏览器均无法直连,SQL 一律经 tcb 代理;看板采用「本机聚合快照 → 静态托管」,刷新即重算。
隐私
账单数据不外发
邮箱凭证仅由连接器注入、不落盘;原始邮件与明细只存在于本机与私有云 MySQL;任何对外输出默认脱敏。
可核对
三方对账
verify_db.py 以原始邮件重解析 + 历史 CSV 双路与 DB 比对。最近核对:金额零差异、币种有区分、外币已折算。
05

调度 · 自动化任务

由 WorkBuddy automation 驱动,无需人工值守。

任务 ID名称计划状态
automation-1785482176723 增量入库 + 看板部署 DAILY · 08:00 ACTIVE
automation-1785482176737 月度账单报告 MONTHLY · 1日 09:00 ACTIVE
automation-1785483716942 看板手动刷新 MANUAL · 按需 STANDBY