使用python实现合并微信个人对账单和支付宝个人交易流水证明
- 下载微信对账单和支付宝个人交易流水证明
- 确保已安装 Python 3.x 和必要的依赖库
pip install -r requirements.txt在项目根目录执行:
python src/main.py --gui窗口顶层为 运行配置、Firefly 配置 与 日志 三个分页:运行配置中选数据来源、账单/明细文件、导出选项与 Firefly 运行模式(预览 / 真实导入 / dry-run),点 运行 后自动切到日志;Firefly 配置 编辑 YAML、校验与测试连接;日志 按前缀着色展示过程与报错。Firefly 预览 会写入全量 Excel 并自动打开;日志中 资产/对方科目规划 按绿(已有)、黄(将建)、红(不可)区分。界面基于 ttkbootstrap(litera 主题)。网络与合并操作在后台线程执行;原始账单 CSV 会自动嗅探渠道,可手动纠错。
打包无控制台 exe(需在项目根安装 PyInstaller)示例:
pyinstaller gui.spec可执行文件旁需能访问 output/、config/;首次运行可复制仓库内示例生成本地配置。
在 仅装了 Firefly III、不部署 Data Importer 的前提下,可将合并后的账单经 REST API 写入账本。
- 币种:启用
CNY(或与defaults.currency_code一致的代码)。 - 账户:为账单 「支付方式」 中出现的每种资金渠道建立对应账户(零钱等多为 Asset;信用卡多为 Debt/负债信用卡)。
- 复式对应科目(默认动态):
defaults.counterparty_accounts默认为true。支出行按 「交易对方」 匹配 Expense(withdrawal.destination);收入行按同一列匹配 Revenue(deposit.source)。匹配时 仅在该类型账户中按名称查找,避免与同名的资产账户混淆。缺失账户仅在 不带--firefly-preview、不带--dry-run的真实导入 时通过 API POST 新建。若账单中对方列为空或为占位符(如单独一根/),则使用兜底科目(「YAML 兜底」见下)。 - 固定科目模式(可选):将
defaults.counterparty_accounts设为false时回到旧行为,此时 必须 填写withdrawal_destination_*与deposit_source_*,不再按交易对方分列。 - 令牌:在用户菜单 → Profile → OAuth / PAT 页面创建 Personal Access Token,仅保存在本机。
counterparty_accounts: true(默认)withdrawal_destination_*/deposit_source_*不必必填;若填写,可作为 兜底链的一部分(先有*_fallback_*,否则再解析这两个字段)。- 「交易对方」无效时请至少配置:
withdrawal_destination_fallback_name(或_account_id)、deposit_source_fallback_name(或_account_id);否则对应行解析失败并报错提示。
- 预览:不 POST 交易、不 POST 收支账户,但会照常打印
[Firefly账户·规划]段落,标明每个 distinct 对方在 Firefly 中是否已有同名 expense/revenue,以及若在「只读场景」则 不会新建。 --dry-run:与预览一致,不向 Firefly 写入任何东西(无交易 POST、无账户 POST)。控制台样例拆分中 不会给出可真实提交的完整金额分录 JSON;缺失对方账户时用「账单对方 + 占位说明」标出。不要在未 dry-run 的 JSON 中伪造尚未创建的source_id/destination_id。- 支付方式兜底:建议在 YAML 配置
default_payment_account_by_source(如微信 → 零钱资产、支付宝 → 余额宝等),账单里「支付方式」为/或未单独写规则时能落到正确资产。payment_accounts可用match_regex匹配银行名+卡号(尾号)与 Firefly 无括号账户名不一致的情况;示例见 config/firefly.local.yaml.example。 - 去重(YAML 顶层,可选):
error_if_duplicate_hash(默认false)为true时,POST 载荷要求 Firefly 对 重复 transaction hash 报错(与external_id含义不同,以实例行为为准)。skip_if_external_id_exists(默认true)为true时,真实导入前对每条调用搜索 APIexternal_id_is:…,已存在则 跳过 POST(请求量约等于条数;搜索失败时视为「未发现」以免误跳过)。同一次运行内若两条明细生成相同的external_id,导入前会 只保留第一条,并在解析警告中汇总。external_id_prefix_order_by_source(默认true)为true时:external_id对交易单号加wx:/zfb:等前缀以降低跨渠道碰撞;无单号/商户号时合成为s1:+ sha256(与旧版synth:不同,曾与旧入库记录并存则须删旧条目或对齐规则)。 - 支付宝合并:默认 剔除「不计收支」列(及可选「交易关闭」),日志会打印剔除笔数——因此合并明细行数常 小于 支付宝 App 中「支出+收入+不计收支」三类笔数之和。若需在合并表中保留转账等「不计收支」行,请在 YAML 设
bill_merge_keep_alipay_neutral: true;GUI 会从firefly.local.yaml读取bill_merge_*后与命令行合并行为一致。 - 导入批次标签(默认开启):
add_import_batch_tag(默认true)为true时,本次运行(含预览解析)为每笔交易附加 一个 批次 tag:若 未 设置import_batch_tag则自动生成import批量:YYYY-mm-dd_HHMMSS;若设置了则使用固定字符串。与原有「渠道:微信」、规则 tags 并列。若同时开启skip_if_external_id_exists与tag_existing_on_skip(默认true),对已存在记录会 GET+PUT 合并该 tag(复杂分录若 API 返回结构不兼容可能失败,以日志为准)。
- 将 config/firefly.local.yaml.example 复制为
config/firefly.local.yaml,填写base_url、access_token。payment_accounts与default_payment_account/default_payment_account_by_source必须指向你 Firefly 里真实存在的资产/负债账户名或整数 ID;若误留仓库占位长文案或未改REPLACE_ME_PAT,加载配置时会直接报错。另见defaults中动态对方与兜底说明。 - 该文件已由
.gitignore忽略,请勿提交。仓库内只保留示例文件。
推荐流程:先预览再导入
# 1. 仅解析:生成 output/firefly_preview_时间戳.xlsx(全量);默认日志仅摘要(可用 --firefly-preview-limit N 额外打印前 N 行);不 POST
python src/main.py --firefly-import --firefly-preview
# 控制台展示行数可调(Excel 仍为全量)
python src/main.py --firefly-import --firefly-preview --firefly-preview-limit 50
# 2. 确认 YAML 后真正写入 Firefly
python src/main.py --firefly-import其他
python src/main.py --firefly-import --dry-run # 不写 Firefly:规划日志 + 最多 10 条拆分样例(缺账户则无完整 POST JSON)
python src/main.py --firefly-import --firefly-config /path/to/my.yaml
# 仅验证 connection(about / 账户 / 抽样类目与预算),不写账单、不 POST;默认读 config/firefly.local.yaml
python src/main.py --firefly-probe
python src/main.py --firefly-probe --firefly-config /path/to/my.yaml说明:
--firefly-preview与--firefly-import同用:只预览、不记账、不建新账户;与「真导入」二选一。导出 Excel 中「对方科目」列在未建库的对方上会显示交易对方+ 「导入时将创建同名 expense/revenue」(不捏造 id)。- 若同时传入
--dry-run与--firefly-preview,将以预览为准(不再走--dry-run单独的样例回路)。 --dry-run(且未启用--firefly-preview)须与--firefly-import同用;不向 Firefly 写入交易或收支账户,仅控制台调试。- 每笔优先将 交易单号 设为
external_id(可带来源前缀),否则 商户单号(无前缀时为merchant:{单号}),否则按上文的s1:哈希规则;支付方式→资产账户:payment_accounts优先匹配,default_payment_account_by_source次之,再default_payment_account;解析失败则在控制台汇总原因。
下载 Release 中打包好的 exe 文件,直接双击执行。
python src/main.py默认行为:
- 导出为 XLSX 格式
- 单文件模式(包含"明细"和"统计"两个工作表)
- 输出文件保存在
./output/目录,文件名带时间戳
Firefly III 导入 (--firefly-import,可选 --firefly-preview、--firefly-preview-limit、--dry-run、--firefly-config);仅连接自检可使用 --firefly-probe(可选 --firefly-config)
python src/main.py --firefly-import --firefly-preview
python src/main.py --firefly-import --dry-run
python src/main.py --firefly-import --firefly-config /path/to/firefly.local.yaml详见上文「Firefly III 导入(可选)」。
收支分离模式 (-s 或 --separate)
python src/main.py -s- 分别导出收入和支出两张表
- 默认 XLSX 格式,输出为
支出_{时间戳}.xlsx和收入_{时间戳}.xlsx
指定输出格式 (-f 或 --format)
python src/main.py -f csv- 支持格式:
xlsx(默认)或csv - CSV 格式下,明细和统计分别输出为两个文件
组合使用
# 收支分离 + CSV 格式
python src/main.py -s -f csv
# 查看帮助信息
python src/main.py -h
# 图形界面
python src/main.py --gui-
默认模式(单文件):
- XLSX 格式:
result_{时间戳}.xlsx(包含"明细"和"统计"两个工作表) - CSV 格式:
result_{时间戳}_明细.csv和result_{时间戳}_统计.csv
- XLSX 格式:
-
收支分离模式:
- XLSX 格式:
支出_{时间戳}.xlsx和收入_{时间戳}.xlsx - CSV 格式:
支出_{时间戳}.csv和收入_{时间戳}.csv
- XLSX 格式:
所有输出文件均保存在 ./output/ 目录中,文件名包含时间戳(格式:YYYYMMDD_HHMMSS),避免文件覆盖。
- ✅ 支持微信账单(CSV/XLSX 格式)
- ✅ 支持支付宝账单(CSV 格式)
- ✅ 支持批量导入多个文件
- ✅ 自动合并微信和支付宝账单
- ✅ 自动生成月度收支统计
- ✅ 支持收支分离导出
- ✅ 支持 XLSX 和 CSV 两种输出格式
- ✅ 可选:Tkinter 图形界面(
python src/main.py --gui,ttkbootstrap litera 主题):运行配置 / Firefly 配置 / 日志 三 Tab、Firefly 预览自动打开 Excel、账户规划绿/黄/红日志 - ✅ 可选:直连 Firefly III REST API;导入前可先
--firefly-preview导出 Excel 预览(账户名、标签、品类等)再写入账本