技能市场

消费账单分析·支付宝微信银行流水记账统计

@user_2ckqg/bill-analysis

个人消费账单分析:读取支付宝、微信、银行流水导出文件,自动识别列、分类、跨来源去重,识别订阅扣费,按月、按类别、按商户统计支出并给出一条可执行的省钱动作。纯本地、不联网、不上传。

来源:千问AI平台数据分析MIT

消费账单分析

这个技能做什么、不做什么

  • 做:把用户自己导出的账单流水(支付宝 / 微信支付 / 银行卡)读进来,识列、归类、去重,
    出一份月度报告——这个月花了多少、花在哪、比上个月多花了多少、有哪些还在扣的订阅、
    哪几笔比自己的常态大得多。全是用户账单上已经发生的事实。
  • 不做:不联网(不查汇率、不查任何行情、不上传任何数据);
    不碰投资理财(股票、基金、理财产品、保险、加密货币一概不在范围内);
    不推荐任何产品、任何平台、任何消费方式;不给「你该怎么省钱」之类的建议。
  • 用户问「这钱该买点什么理财」「XX 基金能不能买」时,明确说这不在本技能范围内,
    把话题拉回「你的账单里这类支出是多少」。
  • 报告里出现的每一个数字,都能在用户自己的账单文件里追溯到具体某一行。

隐私:全部在本地

  • 账单里有商户、金额、对方姓名,属于高敏感数据。本技能只在本机读文件、在本机算、在本机写报告
    不发起任何网络请求,不把任何一行数据发到外部
  • 脚本只读用户在命令行里点名的文件,不扫描目录、不翻用户的其他文件。
  • 输出只有两个文件:bill-YYYY-MM.mdbill-YYYY-MM.json,写在 --out 指定的目录(默认当前目录)。
  • 生成的报告本身也含隐私,往外发之前先提醒用户一句。

使用流程

  1. 让用户自己导出账单(别替用户去登录任何账号):

    • 支付宝 App → 我的 → 账单 → 右上角 → 开具交易流水证明 / 导出账单 → 邮箱收 CSV
    • 微信 → 我 → 服务 → 钱包 → 账单 → 常见问题 → 下载账单 → 邮箱收 CSV
    • 网银 / 手机银行 → 交易明细 → 导出(CSV 或 xlsx)
  2. 先跑一次 --months,确认文件读对了、月份齐不齐:

    python {baseDir}/scripts/bill.py <账单1> [账单2 ...] --months
  3. 出月报(不给 --month 就是账单里最近的一个月):

    python {baseDir}/scripts/bill.py <账单1> [账单2 ...] --month 2026-08 --out <输出目录>
  4. 看「疑似重复」那一节。确认那几对确实是同一笔钱之后,加 --dedup 重跑,数字才准。

  5. 把报告原样展示给用户,再用两三句话点出最扎眼的一两个数字(只指方向,不下判断、不劝)。

命令

{baseDir} 是本技能目录。账单文件可以给多个,会合并成一份报告。

# 只看账单覆盖了哪些月份、每月多少(不出报告,适合先确认文件没读错)
python {baseDir}/scripts/bill.py 支付宝.csv 微信.csv 银行.csv --months

# 单文件月报(默认最近一个月,写到当前目录)
python {baseDir}/scripts/bill.py 微信.csv

# 多文件合并 + 指定月份 + 指定输出目录
python {baseDir}/scripts/bill.py 支付宝.csv 微信.csv 银行.xlsx --month 2026-08 --out ./报告

# 确认过疑似重复之后,真删重复笔再出一次
python {baseDir}/scripts/bill.py 支付宝.csv 微信.csv 银行.csv --dedup --out ./报告

# 用自己的分类规则表(覆盖内置规则)
python {baseDir}/scripts/bill.py 微信.csv --rules {baseDir}/assets/categories.example.json

# 不在终端刷报告正文,只要文件
python {baseDir}/scripts/bill.py 微信.csv --quiet --out ./报告
参数 作用
位置参数 账单文件,给几个都行(CSV / xlsx),自动合并
--month YYYY-MM 要出的月份,默认账单里最近的一个月
--months 只列出账单里有哪些月份和各月合计,不出报告
--rules <json> 自定义分类规则表,命中优先级高于内置规则
--dedup 真删疑似重复(默认只提示不删
--out <目录> 报告输出目录,默认当前目录;写出 bill-YYYY-MM.md 和同名 .json
--quiet 不在终端打印报告正文,只打印两个文件路径

报告里有什么

小节 内容
一、总览 总支出 / 总收入 / 结余 / 笔数,各自与上月对比;笔均、日均;收入来源
二、分类占比与环比 每个分类的金额、占比、笔数、笔均,以及与上月同分类的增减
三、Top 10 单笔大额 本月最大的十笔支出,带日期、对方、说明、来自哪个文件
四、Top 10 高频商户 按笔数排,看钱是被哪几家一点点磨走的
五、周末 vs 工作日 两边的笔数、合计、日均(不是总额直接比,周末只有 8~10 天)
六、订阅型支出 连续 3 个月及以上「同一对方 + 同一金额」的支出,标出本月是否仍在扣、折合一年多少
七、异常大额提示 单笔超过「该分类其余各笔笔均」3 倍的支出(该分类不足 3 笔时不判)
八、疑似重复 同一笔钱在两份账单里各记了一次的配对清单
九、解析情况 每个文件认到的表头行、有效记录数、被跳过的行数、认到的列映射

分类

内置 14 个类目:餐饮、交通、购物、日用、居住、通讯、医疗、教育、娱乐、人情往来、转账、还款、收入、其他。

  • 命中优先级:用户规则 > 内置规则 > 其他

  • 匹配范围是「交易对方 + 商品说明/摘要 + 备注 + 账单自带的交易分类」四项拼起来做包含匹配,
    不含支付方式那一列(不然「招商银行储蓄卡」会把一堆消费误判成银行相关)。

  • 收入笔统一归到「收入」,除非用户规则明确另指一类。

  • 自定义规则表见 assets/categories.example.json,两种写法都认:

    {
      "rules": [{"category": "宠物", "keywords": ["猫粮", "宠物医院"]}],
      "ignore_keywords": ["ATM取现"]
    }

    或者最简单的 {"宠物": ["猫粮", "宠物医院"]}
    ignore_keywords 命中的行整行不计入统计,只在「解析情况」里报个数,
    适合排掉自己往自己账户里搬钱的流水。

  • 分类是关键词猜的,猜错很正常。用户说某笔归错了,就往规则表里加一条,别去改脚本。

去重口径

同一笔钱经常出现两次:微信里记「支付 128 给海底捞」,银行流水里记「财付通-消费 128」。判定条件(四条全中才算):

  1. 时间相差 ≤ 5 分钟;
  2. 金额完全相同;
  3. 收支方向相同;
  4. 来自不同的账单文件,且其中一方的文本里出现「微信 / 财付通 / 支付宝 / 云闪付 / 银联」等通道词。

保留信息多的那一条(写了商户名的微信/支付宝那侧),丢掉银行那侧的通道流水。
默认只在报告里列出来,不删——因为「同一天同样金额买了两次同一件东西」也完全可能是真的。
用户确认过之后再加 --dedup

报告怎么说话

  • 数字先行,不加形容词。说「本月餐饮 424.90 元,占 2.5%,5 笔」,
    不说「餐饮花得有点多」「这个月花超了」「要控制一下」。
  • 不劝、不教、不安慰。异常大额那一节只是「这笔和你自己的常态不一样」,不是「这笔花错了」。
  • 不推荐任何商户、平台、支付方式、省钱办法、记账 App。
  • 用户问「我这样花钱正常吗」,把分类占比那张表念出来,再说一句这只是他自己的数字,没有对照标准。
  • 每份报告结尾固定一句:
    以上全部来自你自己导出的账单文件,只做了归类和加总,没有联网取任何数据,也不构成任何消费或理财建议。
    (脚本已自动附上,不要删。)

口径与边界

  • 识列失败就停:前 30 行里找不到同时含「时间/日期」和「金额」的表头行时,脚本打印第一行并退出。
    把表头发给用户确认,别猜,也别自己改数据文件。
  • 编码:CSV 依次尝试 utf-8-sig、utf-8、gbk、gb18030、utf-16;
    xlsx 用标准库的 zipfile + xml 自己解(共享字符串、内联字符串、日期序列号都处理),
    解析不了会明确报错让用户另存为 CSV;.xls 老格式不支持,直接报错。
  • 表头位置:支付宝/微信/银行的导出前面都有几行说明文字,脚本自动往下找真正的列名行,
    并在报告里写明认的是第几行。
  • 日期与时间分两列(银行常见):以日期列为准,把时间列拼回去;选中的列如果解析不出日期,
    自动换一列能解析出来的。
  • 不计收支:支付宝/微信标「不计收支」的行(余额宝转入、零钱通转入之类)不进支出也不进收入,
    只在「解析情况」里报个数。
  • 交易关闭 / 失败 / 撤销 / 已全额退款的行直接跳过,并报个数。
  • 退款:账单里标成「收入」的退款就按收入计,不去和原始那笔支出对冲(对冲不了,账单里没有配对关系)。
  • 转账和还款算不算「花掉」:脚本把它们当支出统计,但单列成「转账」「还款」两类,
    用户想看「真实消费」时,让用户自己把这两类减掉——不要替用户定义什么叫真实消费。
  • 订阅识别只看「同对方 + 同金额 + 连续月份」,年付、变价、免密小额扣费认不出来;
    账单只覆盖 1~2 个月时这一项本来就判不出来,报告里会直说。
  • 异常大额用的是「该分类其余各笔的笔均」(把这笔自己剔掉再算均值),样本不足 3 笔的分类不判。
  • 不做预算、不做目标、不做预测:没有「这个月还能花多少」,没有「照这个速度年底会花掉多少」。
  • 不改用户的账单文件,一个字节都不写回去。

脚本

脚本 用途
scripts/common.py 账单读取与解析(CSV/xlsx、多编码、找表头、列名模糊匹配、收支判定、分类、疑似重复)
scripts/bill.py 月度报告:总览、分类占比与环比、Top10、周末对比、订阅识别、异常大额、去重清单

纯 Python 3 标准库,零第三方依赖(xlsx 也是自己用 zipfile + xml 解的,不需要 openpyxl)。

assets/ 下有三份可直接跑的虚构样例(sample_alipay.csvsample_wechat.csvsample_bank.csv),
用来演示或自检;references/columns.md 是各家导出格式的列名对照。

# 自检:三份样例合并,应报出 3 对疑似重复、2 笔订阅
python {baseDir}/scripts/bill.py {baseDir}/assets/sample_alipay.csv \
  {baseDir}/assets/sample_wechat.csv {baseDir}/assets/sample_bank.csv --dedup --out .