Skip to content

Xm798/bean-sieve

Repository files navigation

Bean-Sieve

Bean-Sieve 是一个基于规则的 Beancount 账单导入与对账工具。

与传统导入器只做「解析 → 导入」不同,Bean-Sieve 支持将账单与已有账本智能对账——自动识别已手动记录的交易,仅生成缺失条目,避免重复。同时也可作为独立的账单解析器,将各类账单统一导出为通用 CSV/XLSX 格式。

功能特性

  • 解析 支付宝、微信支付、银行信用卡/借记卡等各类账单
  • 对账 与已有 Beancount 账本比对,自动识别已记录交易,补充未记录交易
  • 生成 仅输出缺失的待录入条目,支持规则映射账户
  • 导出 可作为纯账单解析器,将账单统一导出为 CSV/XLSX

安装

作为 CLI 工具安装(推荐)

# 使用 uv(推荐)
uv tool install beancount-sieve

# 使用 pipx
pipx install beancount-sieve

# 或从源码安装
uv tool install git+https://github.com/Xm798/bean-sieve.git

以上命令会将 bean-sieve 安装到 ~/.local/bin(Linux/macOS)或用户 PATH(Windows)。请确保该目录在 PATH 中。

开发安装

# 本地开发
uv sync

# 包含开发依赖
uv sync --extra dev

在其他项目中引入

# 从 Git 安装
uv add git+https://github.com/Xm798/bean-sieve.git

# 从本地路径安装
uv add --editable ../bean-sieve

Shell 自动补全

# Bash - 添加到 ~/.bashrc
eval "$(bean-sieve completion bash)"

# Zsh - 添加到 ~/.zshrc
eval "$(bean-sieve completion zsh)"

# Fish
bean-sieve completion fish > ~/.config/fish/completions/bean-sieve.fish

支持的数据源

支付平台

Provider 名称 格式 说明
alipay 支付宝 CSV 支付宝导出的交易明细
app_store App Store HAR App Store 购买历史 (reportaproblem.apple.com HAR 导出)
jd 京东支付 CSV 京东交易流水导出文件
meituan 美团 CSV 美团交易账单明细导出文件
wechat 微信支付 CSV / XLSX 微信支付账单流水文件

信用卡

Provider 名称 格式 说明
abc_credit 农业银行信用卡 EML 邮件账单
boc_credit 中国银行信用卡 PDF PDF 账单
bocom_credit 交通银行信用卡 EML 邮件账单
bosc_credit 上海银行信用卡 EML 邮件账单
ccb_credit 建设银行信用卡 EML 邮件账单
cgb_credit 广发银行信用卡 EML 邮件账单
cib_credit 兴业银行信用卡 EML 邮件账单
cncb_credit 中信银行信用卡 XLS 网银导出账单
cmb_credit 招商银行信用卡 EML 邮件账单
cmbc_credit 民生银行信用卡 EML 邮件账单
hsbchk_credit 汇丰香港信用卡 CSV 网银导出账单(多卡需加 _<后四位> 后缀)
hxb_credit 华夏银行信用卡 EML 邮件账单

借记卡

Provider 名称 格式 说明
boc_debit 中国银行借记卡 CSV 网银导出账单
abc_debit 农业银行借记卡 XLSX Excel 导出账单
icbc_debit 工商银行借记卡 CSV CSV 导出账单
ccb_debit 建设银行借记卡 XLS XLS 导出账单
bocom_debit 交通银行借记卡 XLS XLS 导出账单
cmb_debit 招商银行借记卡 CSV CSV 导出账单
cib_debit 兴业银行借记卡 XLS XLS 导出账单
pab_debit 平安银行借记卡 XLS/XLSX Excel 导出账单
cncbi_debit 中信银行(国际) CSV 网银导出账单
hsbchk_debit 汇丰香港储蓄账户 CSV 网银导出账单
zabank_debit 众安银行 PDF 综合月结单

更多 Provider 正在开发中。

使用方法

命令行

# 对账:解析账单 + 比对账本 + 生成缺失条目
bean-sieve reconcile data/statement/*.csv -l books/ -o pending.bean

# 仅解析:输出标准化交易
bean-sieve parse data/statement/*.csv

# 导出:将解析结果导出为 CSV 或 XLSX
bean-sieve export data/statement/*.csv -f csv -o output/

# 仅检查:显示对账结果,不生成文件
bean-sieve check data/statement/*.csv -l books/

# 提取账单中的支付方式并交互式映射到账本账户
bean-sieve extract-accounts data/statement/*.csv -l books/

# 从账本历史记录中自动生成规则建议
bean-sieve suggest-rules -l books/

# 列出支持的数据源
bean-sieve providers

# 生成 Shell 自动补全脚本
bean-sieve completion bash

Python API

from pathlib import Path
from bean_sieve.providers import get_provider, list_providers

# 查看所有可用的 Provider
for p in list_providers():
    print(f"{p['id']}: {p['name']} ({p['formats']})")

# 解析支付宝账单
alipay = get_provider("alipay")
transactions = alipay.parse(Path("data/statement/支付宝交易明细.csv"))

for txn in transactions[:5]:
    print(f"{txn.date} | {txn.payee:20s} | {txn.amount:>10} CNY | {txn.description}")

# 解析微信账单
wechat = get_provider("wechat")
transactions = wechat.parse(Path("data/statement/微信支付账单.xlsx"))

配置

配置文件搜索顺序:

  1. 命令行 -c/--config 指定的路径
  2. 当前目录 ./bean-sieve.yaml
  3. 系统配置目录:
    • Linux/macOS: $XDG_CONFIG_HOME/bean-sieve/config.yaml~/.config/bean-sieve/config.yaml
    • Windows: %APPDATA%\bean-sieve\config.yaml

复制 bean-sieve.example.yamlbean-sieve.yaml(当前目录)或 config.yaml(系统配置目录)并根据需要修改:

# 默认设置
defaults:
  currency: CNY
  expense_account: Expenses:FIXME
  income_account: Income:FIXME
  date_tolerance: 0  # 日期模糊匹配容差(天)

# 账户映射(按 provider)
accounts:
  alipay:
    default: Assets:Current:Alipay

  wechat:
    default: Assets:Current:Wechat

# 规则匹配(优先级最高,按顺序匹配)
rules:
  # 正则匹配 description
  - description: ".*瑞幸.*"
    payee: 瑞幸咖啡
    contra_account: Expenses:Food:Coffee

  - description: ".*美团.*外卖.*"
    payee: 美团外卖
    contra_account: Expenses:Food:Delivery

  # 多关键词匹配(OR 逻辑)
  - description: "(滴滴|高德|T3出行)"
    payee: 打车
    contra_account: Expenses:Transport:Taxi

  # 时间范围
  - description: ".*食堂.*"
    time: "11:00-14:00"
    contra_account: Expenses:Food:Lunch

  - description: ".*食堂.*"
    time: "17:00-20:00"
    contra_account: Expenses:Food:Dinner

  # 忽略某些交易
  - description: ".*还款.*"
    ignore: true

账单下载方式

借记卡

银行 下载方式 系统要求 备注
中国银行 个人网上银行 Windows / macOS 卡号登录,复制查询表格保存为 CSV
农业银行 个人网上银行 Windows / macOS 需安装安全控件,macOS 需用 Safari
工商银行 个人网上银行 Windows / macOS 需安装安全控件,macOS 需用 Safari
建设银行 个人网上银行 Windows / macOS Chrome 即可,无需安全控件
交通银行 个人网上银行 Windows / macOS 需安装安全控件,macOS 需用 Safari
招商银行 专业版 PC 客户端 Windows 需安装客户端
兴业银行 个人网上银行 Windows / macOS 需安装安全控件,查询→交易明细查询→流水下载→Excel
平安银行 个人网上银行 Windows / macOS 扫码登录无需安全控件
汇丰香港 HSBC HK Online Banking Windows / macOS 储蓄账户:交易记录页 → Download → CSV,导出文件名为 TransactionHistory.csv
中信银行(国际) inet Online Banking Windows / macOS 账户活动 → 下载 CSV

信用卡

信用卡账单通常通过邮件获取,在发卡行官网或 App 设置账单邮箱即可。部分银行支持网银导出:

银行 下载方式 备注
中信银行 信用卡网银 登录后导出已出账单明细 XLS
汇丰香港 HSBC HK Online Banking 信用卡交易页 → Download → CSV,文件名为 TransactionHistory.csv多张卡时请将下载文件重命名为 TransactionHistory_<卡后四位>.csv(如 TransactionHistory_8888.csv)以便对应账户

其他

平台 下载方式 备注
Apple Report a Problem 登录后 F12 打开控制台,滚动加载完后导出 search 请求为 HAR

信用卡账单管理方式

管理方式 银行 特点
按户管理 招商银行、民生银行、华夏银行、平安银行、浦发银行、北京银行、上海银行 信报、还款、积分按户合并管理
按卡管理 广发银行、建设银行 独立信报,账单日合并独立还款
按卡管理 中信银行、光大银行、交通银行、农业银行、工商银行、兴业银行、中国银行、邮政储蓄 独立信报,独立账单,独立还款。

按户管理的账户在同一个 Liability 账户下持有多张物理卡,账户名本身无法区分——配置 diagnostics.meta_check_accounts 后,Bean-Sieve 会在 posting 上自动注入 card_last4,并对账本中缺失或冲突的 card_last4 元数据输出 lint 诊断。

Provider Metadata 字段

每个 Provider 解析账单时,除了标准字段(日期、金额、描述、收款方等)外,还会将账单中的其他列存入 metadata。可通过 output_metadata 配置控制哪些字段输出到 Beancount 文件。

支付平台

Provider Metadata 字段
alipay category, peer_account, method, status, merchant_id, tx_type, remarks
wechat tx_type, method, status, merchant_id, remarks, order_type, commission, rebate, rebate_currency
jd method, transaction_type, transaction_status, transaction_category, merchant_order_id, notes, refund_amount
meituan tx_type, method, merchant_id, remarks, order_amount
app_store media_type, item_id, adam_id

信用卡

Provider Metadata 字段
boc_credit original_trans_date, original_post_date
bocom_credit original_date, section
cgb_credit original_date, trans_type
cib_credit original_date
cmb_credit posting_date
cmbc_credit posting_date
hxb_credit original_date
hsbchk_credit transaction_status, country, district, direction
abc_credit
bosc_credit
ccb_credit
cncb_credit

借记卡

中国银行 boc_debit

字段 说明
summary 业务摘要
balance 余额
channel 交易渠道/场所
counterparty_account 对方账户账号
cash_remit 钞/汇

农业银行 abc_debit

字段 说明
summary 交易摘要
balance 本次余额
counterparty_account 对方账号
bank 交易行
channel 交易渠道
tx_type 交易类型

工商银行 icbc_debit

字段 说明
summary 摘要
balance 余额
detail 交易详情
location 交易场所
counterparty_account 对方账户

建设银行 ccb_debit

字段 说明
summary 摘要
balance 账户余额
counterparty_account 对方账号
location 交易地点

交通银行 bocom_debit

字段 说明
summary 摘要
balance 余额
method 交易方式
location 交易地点
counterparty_account 对方账户
counterparty_bank 对方开户行

招商银行 cmb_debit

字段 说明
type 交易类型
balance 余额
remark 交易备注

兴业银行 cib_debit

字段 说明
summary 摘要
balance 账户余额
counterparty_bank 对方银行
counterparty_account 对方账号
purpose 用途
channel 交易渠道
remark 备注

平安银行 pab_debit

字段 说明
tx_type 交易类型(转入/转出)
summary 摘要
balance 账户余额
note 备注
counterparty_account 对方账号

众安银行 zabank_debit

字段 说明
balance 交易后余额
counterparty 对手方信息(姓名+账号)
exchange_info 换汇的 sell/buy 详情

汇丰香港 hsbchk_debit

字段 说明
balance 交易后余额
balance_currency 余额币种(与交易币种不同时才输出)

配置示例

全局配置(所有 Provider 生效):

defaults:
  output_metadata:
    - time

Provider 级别配置(仅该 Provider 生效,与全局合并):

providers:
  cib_debit:
    output_metadata:
      - counterparty_bank
      - counterparty_account

output_metadata 写在交易头下,作用于整笔交易;若要把字段写在 posting 行下(如 card_last4 用于区分同一账户下的多张物理卡),使用 posting_metadata

providers:
  hxb_credit:
    posting_metadata:
      - card_last4

对于"按户管理"的账户(同一账户持有多张物理卡,如 HXB/SPDB/CMB),通过 diagnostics.meta_check_accounts 纳入检查后 card_last4 会被自动注入 posting,并在 ledger 缺失/冲突时产生诊断。详见下文 Posting 元数据与诊断

Provider 特定功能

借记卡余额断言 (Balance Directive)

对账后可自动生成 Beancount balance 指令,用于校验账户余额。取账单中最后一笔交易的余额,日期为账单结束日次日。

按 Provider 级别控制,默认关闭:

providers:
  pab_debit:
    accounts:
      "6666": Assets:Bank:PAB:6666
    balance: true

输出示例:

2026-04-01 balance Assets:Bank:PAB:6666  12345.67 CNY

农业银行信用卡 (abc_credit)

农业银行账单会显示刷卡金抵扣金额,但不会在交易明细中体现。Bean-Sieve 支持:

  1. 自动核对:比较解析的消费金额与账单应还金额,判断是否平账
  2. 自动生成刷卡金条目:平账时自动生成刷卡金收入记录

配置

providers:
  abc_credit:
    accounts:
      "1234": Liabilities:Credit:ABC:U-示例卡1234
    # 刷卡金收入账户(生成条目时使用)
    rebate_income_account: Income:Rebate:ABC
    # 关键词:用于识别账本中已存在的刷卡金记录
    rebate_keywords:
      - 刷卡金
      - 返现

去重检测逻辑

配置 rebate_income_accountrebate_keywords 后,对账时会在账本的 Extra 条目中查找:

  • 日期在账单周期内
  • 账户包含卡号后四位
  • 金额精确匹配
  • 描述包含关键词 posting 使用了指定的收入账户

如果找到匹配记录,显示 ✅ 平账 (刷卡金 X.XX 已记录);否则自动生成刷卡金条目。

输出示例

; --- 刷卡金抵扣 ---
2025-11-27 * "农业银行" "刷卡金抵扣 (尾号1234)"
  Liabilities:Credit:ABC:U-示例卡1234  1.33 CNY
  Income:Rebate:ABC

; ============================================================
; 农业银行信用卡 账单核对
; ============================================================
;
; 卡号: 620000******1234 (尾号 1234)
; 账单周期: 2025/10/28-2025/11/27
;
;   解析消费:           32036.00 CNY
;   账单应还:           32034.67 CNY
;   刷卡金抵扣:             1.33 CNY
;
;   状态: ✅ 平账 (刷卡金 1.33)

Posting 元数据与诊断

支付宝/微信等支付平台的账单中,method 字段(如 华夏银行信用卡(1234))指向实际刷卡的物理银行卡。对于"按户管理"的银行(HXB、SPDB、CMB 等),同一个 Liability 账户名下会挂多张物理卡,账户名本身无法区分用的哪张卡——此时需要把 card_last4 写在 posting 下面来消歧。

通过 diagnostics.meta_check_accounts(子串匹配)列出需要检查的账户:

diagnostics:
  meta_check: true
  meta_check_accounts:
    - Liabilities:Credit:HXB
    - Liabilities:Credit:SPDB
    - Liabilities:Credit:CMB

列在这里的账户会同时启用两件事:

  1. Writer 自动注入 —— 输出新交易时在这些账户的 posting 下加 card_last4
2025-03-15 ! "瑞幸咖啡" "拿铁"
  time: "10:23:00"
  Liabilities:Credit:HXB  -28.00 CNY
    card_last4: "1234"
  Expenses:Food:Coffee  28.00 CNY
  1. Metadata 诊断 —— 对账时 card_last4 软校验,匹配照常成立,ledger 中缺失或冲突的以 lint 风格输出在 pending.bean 末尾:
; ============================================================
; Metadata diagnostics (2)
; ============================================================
; books/2025/q1.bean:1234  hint  missing posting meta `card_last4: "1234"` on Liabilities:Credit:HXB
; books/2025/q2.bean:88    warn  posting meta `card_last4` mismatch on Liabilities:Credit:SPDB: ledger "5678", statement "1234"
  • hint — ledger 中该交易没有 card_last4,可照提示补上
  • warn — ledger 中 card_last4 与账单冲突,提示核对(交易本身仍被认为匹配,不会重复生成)

账户名已带卡号的(如 Assets:Bank:ICBC:9999Liabilities:Credit:BOCOM:U-东航金0001)没必要纳入——不列就不做检查,也不产生诊断。

如需恢复旧的硬过滤行为(冲突即视为不同交易、进 missing),显式关闭:

diagnostics:
  meta_check: false

数据格式约定

Transaction 字段

字段 类型 说明
date date 交易日期
time time 交易时间(如有)
amount Decimal 金额(支出为正,收入为负)
currency str 币种
description str 原始描述
payee str 交易对方
card_last4 str 银行卡末四位(银行卡 Provider 直接提取;Alipay/WeChat 从 method 尾部 (XXXX) 中提取)
order_id str 订单号/流水号
provider str 数据源标识
metadata dict 扩展元数据

Metadata 字段

不同 Provider 会提取不同的 metadata:

Alipay:

  • category: 交易分类
  • peer_account: 对方账号
  • method: 收/付款方式
  • status: 交易状态
  • merchant_id: 商家订单号

Wechat:

  • tx_type: 交易类型(商户消费、转账、红包等)
  • method: 支付方式
  • status: 当前状态
  • commission: 服务费(如有)

开发

# 安装开发依赖
uv sync --extra dev

# 运行测试
uv run pytest

# 代码检查
uv run ruff check src/ tests/

# 格式化
uv run ruff format src/ tests/

项目结构

bean-sieve/
├── bean-sieve.example.yaml    # 配置示例
├── bean-sieve.schema.json     # 配置 JSON Schema
├── src/bean_sieve/
│   ├── api.py                 # API 层
│   ├── cli.py                 # CLI 入口
│   ├── core/
│   │   ├── types.py           # 数据类型定义
│   │   ├── sieve.py           # 去重/匹配引擎
│   │   ├── rules.py           # 规则匹配引擎
│   │   ├── preset_rules.py    # 内置预设规则
│   │   ├── output.py          # Beancount 输出生成
│   │   ├── export.py          # CSV/XLSX 导出
│   │   └── suggest.py         # 规则自动生成
│   ├── providers/
│   │   ├── base.py            # Provider 基类
│   │   ├── payment/           # 支付平台(支付宝、微信、京东)
│   │   └── banks/
│   │       ├── credit/        # 信用卡(农行、中行、交行等)
│   │       └── debit/         # 借记卡(建行、工行、平安)
│   └── config/
│       ├── schema.py          # 配置 Schema
│       └── wizard.py          # 账户映射向导
└── tests/

Community

LINUX DO - 社区讨论与交流

License

MIT

About

Rule-based statement importer and reconciler for Beancount

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages