Конфиденциальность данных и комплаенс
Покидают ли данные мою инфраструктуру?
Нет — даже при извлечении из PDF. Bank Statement Parser работает как stateless-библиотека. Вся обработка — разбор, маскирование PII, извлечение из архивов — происходит в вашей локальной оперативной памяти. Гибридный PDF-pipeline использует Ollama для локального инференса LLM — без облачных API. XML-парсеры защищены параметром no_network=True, который блокирует весь исходящий доступ на уровне парсера. Ваши финансовые данные никогда не покидают вашу среду.
Как работает маскирование PII?
Конфиденциальные поля маскируются до передачи в логику вашего приложения. Парсер определяет имена дебиторов, кредиторов, IBAN и почтовые адреса, заменяя их на ***REDACTED*** в выводе консоли и потоковом режиме.
- Маскирование включено по умолчанию в CLI и потоковом ре��име.
- Экспорт файлов (CSV, JSON, Excel) сохраняет немаскированные данные для дальнейшей обработки.
- Показать данные можно через
--show-piiв CLI илиredact_pii=Falseв API.
Является ли процесс извлечения детерминированным?
Да, для структурированных форматов — побайтово идентичный вывод при каждом запуске. При одинаковом входном файле детерминированные парсеры (CAMT, PAIN.001, CSV, OFX, QFX, MT940) всегда да��т одинаковый результат. Без случайности, без инференса модели, без эвристической выборки.
Для гибридного PDF-pipeline извлечение через LLM может давать незначительные отклонения между запусками. Поэтому каждое извлечение из PDF проверяется Золотым правилом (opening + credits − debits == closing), а выявленные расхождения можно просмотреть в интерактивном режиме.
CI обеспечивает детерминизм с помощью 718 тестов при 100% покрытии ветвей, включая property-based фаззинг через Hypothesis.
Каким стандартам комплаенса соответствует проект?
В проекте ведётся документация, совместимая с ISO 13485, с полной прослеживаемостью:
- Количественный реестр рисков с оценкой серьёзности/вероятности и остаточного риска.
- План верификации и валидации с 19 этапами в 5 фазах.
- Процедура контроля изменений с оценкой воздействия и протоколами отката.
- Реестр 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 мс |
Скорость извлечения из PDF зависит от пути маршрутизации: детерминированный (менее секунды), Text-LLM (секунды), Vision-LLM (секунды на страницу).
Как обрабатываются большие файлы?
Streaming с ограниченной памятью — протестировано на 50 000 транзакциях в файле. Используйте parse_streaming() для инкрементальной обработки XML. Каждая тран��акция выдаётся как словарь; элементы очищаются после обработки, предотвращая рост памяти. Потребление памяти не зависит от размера файла — тест на 50 000 транзакций (25+ МБ) использует менее чем в 2 раза больше памяти, чем тест на 10 000.
Для файлов более 50 МБ (например, host-to-host пакеты PAIN.001 с 100 000+ платежей) парсер работает через временный файл с chunk-based удалением пространств имён — полный документ никогда не загружается в память.
Как обеспечивается безопасность ZIP-архивов?
iter_secure_xml_entries() проверяет каждую запись перед извлечением:
- Лимит размера записи (по умолчанию 10 МБ)
- Лимит общего несжатого размера (по умолчанию 50 МБ)
- Лимит степени сжатия (по умолчанию 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 Bank-to-Customer Statement | .xml |
CamtParser |
| PAIN.001 | ISO 20022 Credit Transfer Initiation | .xml |
Pain001Parser |
| CSV | Общий банковский экспорт | .csv |
CsvStatementParser |
| OFX | Open Financial Exchange | .ofx |
OfxParser |
| QFX | Quicken Financial Exchange | .qfx |
QfxParser |
| MT940 | Стандарт SWIFT | .mt940, .sta |
Mt940Parser |
| Цифровые и сканированные выписки | .pdf |
smart_ingest() |
Как работает гибридный PDF-pipeline?
Гибридный pipeline (v0.0.5+) автоматически направляет PDF по трём путям извлечения:
- Путь A (детерминированный): таблицы в структурированных PDF разбираются напрямую — бесплатно, быстрее всего, без LLM.
- Путь B (Text-LLM): цифровые PDF со сложной вёрсткой обрабатываются через локальную LLM (LiteLLM/Ollama).
- Путь C (Vision-LLM): отсканированные или копированные выписки обрабатываются мультимодальными моделями.
Каждое извлечение проверяется Золотым правилом (opening + credits − debits == closing). Расхождения можно просмотреть в интерактивном режиме через --type review.
Обрабатывает ли парсер банковские диалекты CAMT.053?
Да — не зависит от пространств имён по задумке. Парсер удаляет пространства имён XML перед обработкой, работая с любым вариантом CAMT.053 (camt.053.001.02, camt.053.001.04 или проприетарные обёртки банков) без настройки. XPath-запросы нацелены на структуру элементов, а не на URI пространств имён.
Для банков, которые оборачивают CAMT в нестандартный конверт, используйте from_string() или from_bytes() для прямой подачи внутреннего документа.
Можно ли сопоставить нестандартные заголовки CSV со стандартной схемой?
Да — автоматическая нормализация, без настройки. CsvStatementParser распознаёт типичные варианты заголовков: "Date", "Transaction Date", "Booking Date" — все сопоставляются с полем date. "Amount", "Value", "Sum" — с полем amount. Раздельные столбцы кредита/дебета (например, "Credit" и "Debit") обнаруживаются и объединяются в одну знаковую сумму автоматически.
Какой формат вывода?
Все парсеры создают стандартизированные DataFrames pandas с едиными типами столбцов:
| Формат | Ключевые столбцы |
|---|---|
| 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 DataFrames, hledger или beancount.
PDF и LLM
Какие LLM-модели поддерживает гибридный pipeline?
Pipeline использует LiteLLM как уровень абстракции моделей и прямой мост Ollama для vision-запросов. Рекомендуемые модели:
- Извлечение текста: любая модель, совместимая с LiteLLM (локальная или удалённая).
- Vision-извлечение:
ollama/minicpm-v(рекомендуется) для сканированных PDF. - Категоризация: любая модель, совместимая с LiteLLM.
Все модели могут работать 100% локально через Ollama — API-ключи не требуются.
Что такое проверка по Золотому правилу?
Каждое извлечение из PDF проверяется уравнением: opening balance + credits − debits == closing balance. Результаты размечаются как:
- 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+). Экспорт транзакций в форматы plaintext-accounting с маппингом счетов:
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 (входящая отчётность). Оба поддерживают streaming, маскирование PII и экспорт в CSV, JSON, Excel, hledger и beancount. Используйте detect_statement_format() для автоматического определения формата.
Что происходит при некорректной записи транзакции?
Поведение зависит от режима разбора:
parse()(пакетный режим) -- Некорректные записи без обязательных полей (Amount,CurrencyилиCdtDbtInd) пропускаются с записью предупреждения. Остальная часть выписки разбирается нормально.parse_streaming()(потоковый режим) -- Ошибки разбора немедленно передаются как исключения. Без тихой потери данных. Такое fail-fast поведение специально для финансовых сценариев, где каждая транзакция должна быть учтена.smart_ingest()(гибридный PDF) -- Ошибки извлечения фиксируются вIngestResultсо статусом проверки, что позволяет интерактивный просмотр.
Как работает дедупликация?
Каждой транзакции присваивается идемпотентный transaction_hash (MD5-отпечаток) на основе ключевых полей. Это позволяет безопасно загружать данные инкрементально — повторная обработка одного файла даёт те же hash, и дубли обнаруживаются автоматически.
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-pipeline
pip install 'bankstatementparser[hybrid]' # Text-LLM путь
pip install 'bankstatementparser[hybrid-vision]' # 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-- DataFrames и обработка данныхopenpyxl-- Экспорт в Excelpydantic-- Валидация данных и моделиdefusedxml-- ��ащита от XXE
Дополнительные модули добавляют: litellm, pypdf, pdfplumber, pypdfium2, fastapi, uvicorn, polars.
Все зависимости имеют SHA-256 hash-lock. CycloneDX SBOM описывает каждый runtime-компонент.
Работает ли на 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=False,no_network=True,load_dtd=False - Защита от ZIP-бомб: лимит степени сжатия, ограничение размера записи, отклонение зашифрованных записей
- Предотвращение обхода путей: блокировка опасных шаблонов и разрешение символических ссылок
- Валидация ввода: ограничение размера файла (100 МБ по умолчанию), проверка расширения/формата
- Цепочка поставок: SHA-256 hash-lock зависимостей, CycloneDX SBOM, аттестация происхождения сборки
- Подписанные коммиты: принудительно в CI
- Локальные LLM: гибридный PDF-pipeline использует Ollama — без облачных API
Чем Bank Statement Parser отличается от pyiso20022?
pyiso20022 — это универсальный инструментарий ISO 20022, генерирующий dataclasses Python из XML-схем ISO. Он охватывает широкий спектр типов сообщений ISO 20022 (PACS, PAIN, CAMT, ADMI) с валидацией схем. Bank Statement Parser создан для разбора банковских выписок с поддержкой гибридного PDF, проверкой баланса, обогащением данных, экспортом в бухгалтерию и единым API для семи форматов, включая не-ISO (CSV, OFX, QFX, MT940, PDF). Если вам нужно разобрать банковские выписки в DataFrames с безопасностью production-уровня, используйте Bank Statement Parser. Если нужен полный каталог сообщений ISO 20022, используйте pyiso20022.
Каковы сроки миграции SWIFT ISO 20022?
SWIFT опубликовал поэтапный план миграции:
- Ноябрь 2026: структурированные и гибридные адреса станут обязательными. Мультиинструкционные сообщения MT101 будут отклонены. Начинается Фаза 1 управления делами.
- Ноябрь 2027: все финансовые учреждения должны уметь принимать CAMT.053. SWIFT прекратит конвертацию MT в ISO-формат.
- Ноябрь 2028: полное прекращение MT940, MT942, MT950, MT900 и MT910. Их заменят CAMT.052, CAMT.053 и CAMT.054.
Bank Statement Parser поддерживает и устаревший MT940, и современные форматы CAMT.053/PAIN.001, что делает его идеальным для переходного периода.