常问问题

关于银行对账单解析器的常见问题

数据隐私与合规

是否有数据离开我的基础设施?

不会——即使 PDF 提取也不会。 Bank Statement Parser 作为无状态库运行。所有处理——解析、PII 脱敏、归档提取——均在本地运行时内存中进行。混合 PDF 管道使用 Ollama 进行本地 LLM 推理——无需云端 API。XML 解析器使用 no_network=True 加固,在解析器层面阻止所有出站访问。您的财务数据永远不会离开您的环境。

PII 脱敏如何工作?

敏感字段在到达应用程序逻辑之前即被屏蔽。解析器识别借方姓名、贷方姓名、IBAN 和邮政地址,在控制台输出和流模式下将其替换为 ***REDACTED***

  • 脱敏在 CLI 输出和流模式下默认开启
  • 文件导出(CSV、JSON、Excel)保留未脱敏的数据以供下游处理。
  • 选择显示完整数据:CLI 使用 --show-pii,API 使用 redact_pii=False

提取过程是确定性的吗?

对于结构化格式是的——每次运行输出字节一致。 给定相同的输入文件,确定性解析器(CAMT、PAIN.001、CSV、OFX、QFX、MT940)每次产生相同的结果。无随机性,无模型推理,无启发式采样。

对于混合 PDF 管道,基于 LLM 的提取路径可能在运行之间产生微小差异。因此每次 PDF 提取都通过黄金法则opening + credits − debits == closing)验证,标记的差异可通过交互式审查处理。

CI 通过 718 项测试(100% 分支覆盖率)强制确保确定性,包括基于 Hypothesis 的属性模糊测试。

该项目遵循哪些合规标准?

该项目维护符合 ISO 13485 的文档,具有完整可追溯性:

  • 量化的风险登记册,包含严重性/概率评分和残余风险评估。
  • 验证与确认计划,包含 5 个阶段共 19 个门控步骤。
  • 变更控制流程,带有影响评估和回滚协议。
  • SOUP 登记册,涵盖所有依赖项及其风险等级和 EOL 跟踪。
  • 可追溯性矩阵,将设计输入映射到实现和验证。

每个版本均包含 CycloneDX SBOM、SHA-256 校验和以及 GitHub 构建来源证明。

性能与可扩展性

Bank Statement Parser 有多快?

性能阈值在每次提交时通过 CI 验证:

指标 数值
CAMT.053 吞吐量 27,000+ 笔交易/秒
PAIN.001 吞吐量 52,000+ 笔交易/秒
单笔交易延迟(CAMT) 37 微秒
单笔交易延迟(PAIN.001) 19 微秒
首次返回结果 < 2 ms

PDF 提取速度取决于路由路径:确定性(亚秒级)、文本 LLM(秒级)、视觉 LLM(每页秒级)。

如何处理大文件?

有界内存流式处理——已在每文件 50,000 笔交易下测试。 使用 parse_streaming() 增量处理 XML 文件。每笔交易以字典形式逐一产出;处理后清除元素以防止内存增长。内存不随文件大小扩展——50K 笔交易测试(25+ MB)使用的内存不到 10K 笔交易测试的 2 倍。

对于超过 50 MB 的文件(例如包含 100K+ 笔支付的主机到主机 PAIN.001 批次),解析器通过基于分块命名空间剥离的临时文件进行流处理——完整文档永远不会加载到内存中。

ZIP 归档如何安全处理?

iter_secure_xml_entries() 在提取前验证每个成员:

  • 条目大小上限(默认每个条目 10 MB)
  • 总解压大小上限(默认 50 MB)
  • 压缩比限制(默认 100:1)以防止 ZIP 炸弹
  • 加密条目拒绝

无文件写入磁盘。XML 字节通过 from_bytes() 直接传递给解析器。

可以并行解析多个文件吗?

可以。 使用 parse_files_parallel(),它通过 ProcessPoolExecutor 分配工作:

from bankstatementparser import parse_files_parallel

results = parse_files_parallel([
    "statements/jan.xml",
    "statements/feb.xml",
    "statements/mar.xml",
])
for r in results:
    print(r.path, r.status, len(r.transactions), "rows")

对于批量 PDF 摄取,使用 scan_and_ingest(),它处理整个文件夹树并自动去重。

支持的格式

支持哪些银行对账单格式?

格式 标准 文件类型 解析器/方法
CAMT.053 ISO 20022 银行对客户对账单 .xml CamtParser
PAIN.001 ISO 20022 贷记转账发起 .xml Pain001Parser
CSV 通用银行导出 .csv CsvStatementParser
OFX Open Financial Exchange .ofx OfxParser
QFX Quicken Financial Exchange .qfx QfxParser
MT940 SWIFT 标准 .mt940, .sta Mt940Parser
PDF 数字和扫描对账单 .pdf smart_ingest()

混合 PDF 管道如何工作?

混合管道(v0.0.5+)智能地将 PDF 路由至三条提取路径:

  • 路径 A(确定性):直接解析结构化 PDF 表格——免费、最快,无需 LLM。
  • 路径 B(文本 LLM):布局复杂的数字 PDF 通过本地 LLM(LiteLLM/Ollama)提取。
  • 路径 C(视觉 LLM):扫描件或复印件通过多模态视觉模型处理。

每次提取均通过黄金法则(opening + credits − debits == closing)验证。差异可通过 --type review 进行交互式审查。

解析器是否处理 CAMT.053 的银行特定方言?

是的——设计上与命名空间无关。 解析器在处理前剥离 XML 命名空间,可处理任何 CAMT.053 变体(camt.053.001.02camt.053.001.04 或专有银行包装器),无需命名空间特定配置。XPath 查询目标是元素结构,而非命名空间 URI。

对于将 CAMT 包装在自定义信封中的银行,使用 from_string()from_bytes() 直接传入内部文档。

可以将自定义 CSV 列标题映射到标准模式吗?

可以——自动标准化,零配置。 CsvStatementParser 识别常见的标题变体:"Date""Transaction Date""Booking Date" 都映射到 date 字段。"Amount""Value""Sum" 映射到 amount。拆分的贷方/借方列(例如 "Credit""Debit")会被自动检测并合并为单一带符号金额。

输出格式是什么?

所有解析器均生成具有一致列类型的标准化 pandas DataFrame:

格式 关键列
CAMT Amount, Currency, DrCr, Debtor, Creditor, Reference, ValDt, BookgDt, AccountId
PAIN.001 PmtInfId, PmtMtd, InstdAmt, Currency, CdtrNm, EndToEndId, MsgId, CreDtTm, NbOfTxs
CSV/OFX/QFX/MT940 date, description, amount(标准化)

还可导出为 CSV、JSON、Excel、Polars DataFrame、hledger 或 beancount 日记账格式。

PDF 和 LLM 功能

混合管道支持哪些 LLM 模型?

管道使用 LiteLLM 作为模型抽象层,并为视觉提示提供直接的 Ollama 桥接。推荐模型:

  • 文本提取:任何 LiteLLM 兼容模型(本地或远程)。
  • 视觉提取ollama/minicpm-v(推荐),用于扫描 PDF。
  • 分类:任何 LiteLLM 兼容模型。

所有模型均可通过 Ollama 100% 本地运行——无需 API 密钥。

什么是黄金法则校验?

每次 PDF 提取都通过以下等式验证:期初余额 + 贷方 − 借方 == 期末余额。结果标记为:

  • VERIFIED:余额精确匹配。
  • DISCREPANCY:余额不匹配——建议审查。
  • FAILED:无法执行校验(缺少余额数据)。

可以自动分类交易吗?

可以。 分类模块(v0.0.6+)提供 LLM 驱动的交易分类:

from bankstatementparser.enrichment import Categorizer

categorizer = Categorizer()
enriched = categorizer.categorize_batch(transactions)

默认模式使用 13 个 Plaid 兼容类别。您可以提供自定义类别模式。

可以导出到 hledger 或 beancount 吗?

可以(v0.0.8+)。将交易导出为带账户映射的纯文本记账日记账格式:

from bankstatementparser.export import to_hledger, to_beancount

journal = to_hledger(transactions, account="Assets:Bank:Checking")

资金管理工作流

解析器如何处理多币种对账单?

每笔交易保留其原始货币——无隐式转换。 Currency 字段从 XML Ccy 属性中逐笔提取。多币种对账单保持原样。get_account_balances() 方法返回每个账户的期初和期末余额及原始币种代码。

自 v0.0.8 起,verify_balance_multi_currency() 按币种分组并独立运行黄金法则——适用于持有多种货币的账户。

解析器是否同时支持付款和收款格式?

是的。 Pain001Parser 处理 ISO 20022 PAIN.001 贷记转账发起文件(付款)。CamtParser 处理 CAMT.053 银行对客户对账单文件(收款报告)。两者均支持流式处理、PII 脱敏,以及导出到 CSV、JSON、Excel、hledger 和 beancount。使用 detect_statement_format() 自动识别格式。

交易条目格式错误时会怎样?

行为取决于解析模式:

  • parse()(批处理模式) -- 缺少必填字段(AmountCurrencyCdtDbtInd)的格式错误条目将被跳过并记录警告。其余对账单正常解析。
  • parse_streaming()(流模式) -- 解析错误立即作为异常传播。无静默数据丢失。这种快速失败行为是为必须核算每笔交易的金融工作流而设计的。
  • smart_ingest()(混合 PDF) -- 提取错误被捕获到 IngestResult 中,附带校验状态,支持交互式审查。

去重如何工作?

每笔交易被分配一个幂等的 transaction_hash(MD5 指纹),基于其关键字段生成。这使得安全的增量摄取成为可能——重新处理同一文件产生相同的哈希,重复项被自动检测。

from bankstatementparser import CamtParser, Deduplicator

parser = CamtParser("statement.xml")
dedup = Deduplicator()
result = dedup.deduplicate(dedup.from_dataframe(parser.parse()))

print(f"Unique: {len(result.unique_transactions)}")
print(f"Exact duplicates: {len(result.exact_duplicates)}")
print(f"Suspected matches: {len(result.suspected_matches)}")

安装与兼容性

如何安装 Bank Statement Parser?

# 核心安装(仅确定性解析器)
pip install bankstatementparser

# PDF 混合管道
pip install 'bankstatementparser[hybrid]'         # 文本 LLM 路径
pip install 'bankstatementparser[hybrid-vision]'   # 视觉 LLM 路径

# 扩展功能
pip install 'bankstatementparser[enrichment]'      # 交易分类
pip install 'bankstatementparser[api]'             # REST API 微服务
pip install 'bankstatementparser[polars]'          # Polars DataFrame 支持

支持哪些 Python 版本?

Python 3.10 至 3.14。Python 3.9 支持已在 v0.0.6 中移除(EOL 2025-10-31)。所有版本均在 CI 中通过 718 项测试(100% 分支覆盖率)。

有哪些依赖项?

核心库有 5 个直接依赖项:

  • lxml -- XML 解析及安全加固
  • pandas -- DataFrame 和数据处理
  • openpyxl -- Excel 导出
  • pydantic -- 数据验证和模型
  • defusedxml -- XXE 防护

可选扩展添加:litellmpypdfpdfplumberpypdfium2fastapiuvicornpolars

所有依赖项均有 SHA-256 哈希锁定版本。CycloneDX SBOM 映射每个运行时组件。

支持 macOS、Linux 和 Windows 吗?

是的。 该库适用于 macOS、Linux 和 Windows(通过 WSL)。没有平台特定依赖。

有 REST API 吗?

(v0.0.8+)。安装 pip install 'bankstatementparser[api]' 后运行:

bankstatementparser-api --port 8000

端点:POST /ingest(解析对账单)和 GET /health(健康检查)。

可复现性与安全

如何验证可复现性?

python -m pytest                              # 718 tests, 100% branch coverage
python scripts/verify_locked_hashes.py        # SHA-256 hash verification
git log --show-signature -1                   # Verify commit signature

内置了哪些安全保护?

  • XXE 防护resolve_entities=Falseno_network=Trueload_dtd=False
  • ZIP 炸弹防护:压缩比限制、条目大小上限、加密条目拒绝
  • 路径遍历防护:危险模式黑名单和符号链接解析
  • 输入验证:文件大小限制(默认 100 MB)、扩展名/格式验证
  • 供应链:SHA-256 哈希锁定依赖、CycloneDX SBOM、构建来源证明
  • 签名提交:在 CI 中强制执行
  • 仅限本地 LLM:混合 PDF 管道使用 Ollama——无云端 API 调用

Bank Statement Parser 与 pyiso20022 相比如何?

pyiso20022 是一个通用 ISO 20022 工具包,从 ISO XML 模式生成 Python 数据类。它涵盖广泛的 ISO 20022 消息类型(PACS、PAIN、CAMT、ADMI)及模式验证。Bank Statement Parser 专为银行对账单解析而构建,具有混合 PDF 支持、余额校验、智能分类、账本导出,以及跨七种格式(包括非 ISO 格式 CSV、OFX、QFX、MT940、PDF)的统一 API。如果您需要将银行对账单解析为具有生产级安全性的 DataFrame,请使用 Bank Statement Parser。如果您需要使用完整的 ISO 20022 消息目录,请使用 pyiso20022。

SWIFT ISO 20022 迁移截止日期是什么?

SWIFT 发布了分阶段迁移时间表:

  • 2026 年 11 月:结构化和混合地址成为强制要求。MT101 多指令消息将被拒绝。案例管理第一阶段开始。
  • 2027 年 11 月:所有金融机构必须能够原生接收 CAMT.053 对账单。SWIFT 将停止将 MT 转换为 ISO 格式。
  • 2028 年 11 月:MT940、MT942、MT950、MT900 和 MT910 完全退役。将由 CAMT.052、CAMT.053 和 CAMT.054 等效格式取代。

Bank Statement Parser 同时支持传统 MT940 格式和现代 CAMT.053/PAIN.001 格式,是过渡期间的理想选择。