Архитектура
Три слоя
┌─────────────────────────────────────────┐│ webapp (FastAPI + htmx на 127.0.0.1) │ ← взаимодействие с пользователем├─────────────────────────────────────────┤│ cli (argparse — подкоманды anonymize) │ ← скрипты / автоматизация├─────────────────────────────────────────┤│ core (парсеры, детекция, токены, │ ← чистый Python, без сети│ writer'ы, языковые пакеты) │└─────────────────────────────────────────┘core — обычный Python-пакет без сетевых зависимостей. Интеграционный тест в CI проверяет, что во время обычной обработки документа ни один сокет не открывается.
CLI и веб-приложение оба зависят от core и предоставляют разные интерфейсы для одних и тех же операций.
Обновлениями занимается отдельный процесс anonymizer.updater — см. Обновления.
Поток данных для одного файла
- Parse —
core.parsersчитает.docx(python-docx + lxml),.pdf(PyMuPDF, с локальным Tesseract OCR для сканированных страниц) или.xlsx(openpyxl + lxml) - Detect — зарегистрированные детекторы проходят по распарсенному тексту. Regex-детекторы (email, телефоны, IBAN) и NER-детекторы (spaCy + Natasha для имён, адресов, компаний) выдают записи
Entityсо смещениями - Tokenize —
TokenManagerприсваивает стабильные ID для каждой категории ([Person_1],[Person_2], …) в рамках сессии - Write —
core.writersсоздаёт новый файл, в котором найденные spans заменены на токены. Исходная структура (ячейки таблиц, разметка страниц, формулы) сохраняется - Очистка метаданных —
core.metadataудаляет авторство, историю комментариев и информацию о ревизиях из выходного контейнера
Исходный файл никогда не изменяется.
Расширяемые детекторы
Детекторы реализуют простой интерфейс:
class Detector(Protocol): name: str category: str enabled_by_default: bool
def detect(self, doc: ParsedDoc) -> list[Entity]: ...Регистрируются в core.detection.registry. См. Каталог детекторов.
Расширяемые языковые пакеты
NER-детекторы делегируют работу в LanguagePack. Русский (Natasha) и английский (spaCy) встроены; испанский, немецкий и итальянский — опциональные модели. Добавление нового языка не требует изменений в core.detection или core.tokens.
См. Языковые пакеты.