Bean-Sieve 是一个基于规则的 Beancount 账单导入与对账工具。
与传统导入器只做「解析 → 导入」不同,Bean-Sieve 支持将账单与已有账本智能对账——自动识别已手动记录的交易,仅生成缺失条目,避免重复。同时也可作为独立的账单解析器,将各类账单统一导出为通用 CSV/XLSX 格式。
- 解析 支付宝、微信支付、银行信用卡/借记卡等各类账单
- 对账 与已有 Beancount 账本比对,自动识别已记录交易,补充未记录交易
- 生成 仅输出缺失的待录入条目,支持规则映射账户
- 导出 可作为纯账单解析器,将账单统一导出为 CSV/XLSX
# 使用 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# 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 账单 | |
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 |
众安银行 | 综合月结单 |
更多 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 bashfrom 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"))配置文件搜索顺序:
- 命令行
-c/--config指定的路径 - 当前目录
./bean-sieve.yaml - 系统配置目录:
- Linux/macOS:
$XDG_CONFIG_HOME/bean-sieve/config.yaml或~/.config/bean-sieve/config.yaml - Windows:
%APPDATA%\bean-sieve\config.yaml
- Linux/macOS:
复制 bean-sieve.example.yaml 为 bean-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。可通过 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 |
— |
| 字段 | 说明 |
|---|---|
summary |
业务摘要 |
balance |
余额 |
channel |
交易渠道/场所 |
counterparty_account |
对方账户账号 |
cash_remit |
钞/汇 |
| 字段 | 说明 |
|---|---|
summary |
交易摘要 |
balance |
本次余额 |
counterparty_account |
对方账号 |
bank |
交易行 |
channel |
交易渠道 |
tx_type |
交易类型 |
| 字段 | 说明 |
|---|---|
summary |
摘要 |
balance |
余额 |
detail |
交易详情 |
location |
交易场所 |
counterparty_account |
对方账户 |
| 字段 | 说明 |
|---|---|
summary |
摘要 |
balance |
账户余额 |
counterparty_account |
对方账号 |
location |
交易地点 |
| 字段 | 说明 |
|---|---|
summary |
摘要 |
balance |
余额 |
method |
交易方式 |
location |
交易地点 |
counterparty_account |
对方账户 |
counterparty_bank |
对方开户行 |
| 字段 | 说明 |
|---|---|
type |
交易类型 |
balance |
余额 |
remark |
交易备注 |
| 字段 | 说明 |
|---|---|
summary |
摘要 |
balance |
账户余额 |
counterparty_bank |
对方银行 |
counterparty_account |
对方账号 |
purpose |
用途 |
channel |
交易渠道 |
remark |
备注 |
| 字段 | 说明 |
|---|---|
tx_type |
交易类型(转入/转出) |
summary |
摘要 |
balance |
账户余额 |
note |
备注 |
counterparty_account |
对方账号 |
| 字段 | 说明 |
|---|---|
balance |
交易后余额 |
counterparty |
对手方信息(姓名+账号) |
exchange_info |
换汇的 sell/buy 详情 |
| 字段 | 说明 |
|---|---|
balance |
交易后余额 |
balance_currency |
余额币种(与交易币种不同时才输出) |
全局配置(所有 Provider 生效):
defaults:
output_metadata:
- timeProvider 级别配置(仅该 Provider 生效,与全局合并):
providers:
cib_debit:
output_metadata:
- counterparty_bank
- counterparty_accountoutput_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 元数据与诊断。
对账后可自动生成 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
农业银行账单会显示刷卡金抵扣金额,但不会在交易明细中体现。Bean-Sieve 支持:
- 自动核对:比较解析的消费金额与账单应还金额,判断是否平账
- 自动生成刷卡金条目:平账时自动生成刷卡金收入记录
providers:
abc_credit:
accounts:
"1234": Liabilities:Credit:ABC:U-示例卡1234
# 刷卡金收入账户(生成条目时使用)
rebate_income_account: Income:Rebate:ABC
# 关键词:用于识别账本中已存在的刷卡金记录
rebate_keywords:
- 刷卡金
- 返现配置 rebate_income_account 或 rebate_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)
支付宝/微信等支付平台的账单中,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列在这里的账户会同时启用两件事:
- 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
- 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:9999、Liabilities:Credit:BOCOM:U-东航金0001)没必要纳入——不列就不做检查,也不产生诊断。
如需恢复旧的硬过滤行为(冲突即视为不同交易、进 missing),显式关闭:
diagnostics:
meta_check: false| 字段 | 类型 | 说明 |
|---|---|---|
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 | 扩展元数据 |
不同 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/
LINUX DO - 社区讨论与交流
MIT