Andrey Kruchinkin 49f91247c7 Каталогизатор документов: разбор папки, тезисы, поиск, GUI
Программа принимает папку с документами, извлекает из них текст и
метаданные и строит каталог: краткое описание, тезисы и ключевые слова
для каждого файла плюс поиск по всему собранному.

Ядро:
- extract: PDF, DJVU, DOC(X), RTF, ODT, CHM, EPUB, FB2, PPT(X), XLS(X), TXT;
  PDF передаётся MuPDF потоком в память (работают длинные пути) и ограничен
  по времени — повреждённый файл иначе чинится минутами;
- summarize: экстрактивное реферирование по TF-IDF, посчитанному на самой
  библиотеке, с лёгким стеммером для русского и английского;
- db: SQLite с полнотекстовым индексом FTS5, морфологический поиск с BM25;
- scanner: инкрементальный многопоточный обход, счётчик попыток защищает
  от файла, обрывающего разбор;
- report: автономный HTML с поиском, Markdown, JSON, CSV.

Интерфейс:
- окно PySide6 в тёмной теме: вкладки разбора и поиска, фоновый поток,
  карточка документа, правка своих ключевых слов;
- командная строка: build, scan, analyze, report, search, show, tag, stats;
- у каждой папки свой каталог, последняя обработанная запоминается.

Сборка: scripts/build_exe.py даёт Catalogizer.exe в Windows и
Catalogizer.app в macOS, иконки .ico и .icns рисуются кодом.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 19:20:29 +03:00

Каталогизатор документов

Программа принимает папку с документами, разбирает её и строит каталог: для каждого файла — краткое описание, тезисы и ключевые слова, плюс поиск по каталогу — в окне программы, в командной строке и в автономной HTML-странице.

Всё работает локально: файлы только читаются, никаких обращений в сеть.

Программа работает в Windows, macOS и Linux — исходники одни и те же.

Запуск

Windows — двойной щелчок по CATALOG.bat или dist\Catalogizer.exe. macOS — двойной щелчок по CATALOG.command или dist/Catalogizer.app. Ни Python, ни библиотек при этом не требуется.

Из исходников (любая система):

pip install -r requirements.txt
python catalog_gui.py

Окно программы

Две вкладки:

  • Разбор папки — поле пути и «Обзор…», параметры (потоков чтения, страниц на документ, «перечитать всё заново»), кнопки «Построить каталог» и «Остановить», индикатор хода работы и журнал. Разбор идёт в фоновом потоке, окно не подвисает; остановка безопасна — разобранное уже в базе, следующий запуск продолжит с того же места.
  • Каталог и поиск — строка поиска, фильтры по формату, языку и разделу, таблица найденного и карточка документа с описанием, тезисами, ключевыми словами и фрагментом текста с подсветкой. Двойной щелчок открывает документ, «Показать в папке» — проводник на нём.

Кнопки «Пересобрать отчёты» и «Открыть HTML-каталог» — на вкладке разбора.

Командная строка

Папка — обычный аргумент:

python catalog.py build "E:\Yandex.Disk\литература"
Команда Что делает
gui [ПАПКА] графическое окно (то же, что запуск без аргументов)
scan ПАПКА обход папки, извлечение текста и метаданных в базу
analyze ключевые слова, тезисы и описания по всей библиотеке
report выгрузка catalog.html, catalog.md, catalog.json, catalog.csv
build ПАПКА полный цикл: scan + analyze + report
search ЗАПРОС поиск по каталогу
show ID|ИМЯ карточка одного документа
tag ДОКУМЕНТ СЛОВА свои ключевые слова документа
stats сводка: форматы, разделы, частые темы

Последняя обработанная папка запоминается, поэтому дальше путь можно не повторять: python catalog.py search "инвертор". Обратиться к другому каталогу — ключ -c: python catalog.py -c "D:\books" stats.

У каждой папки своя база (catalogs/<имя>-<хеш>.db) и своя папка отчётов (out/<имя>-<хеш>/), каталоги разных папок не смешиваются.

Полезные ключи scan/build:

python catalog.py scan --ext pdf djvu     # только выбранные форматы
python catalog.py scan --max-pages 40     # читать больше страниц из каждого файла
python catalog.py scan --jobs 8           # потоков чтения: HDD 2-4, SSD 8-16
python catalog.py scan --limit 50         # пробный прогон на 50 файлах
python catalog.py scan --force            # перечитать всё заново
python catalog.py scan --retry-broken     # снова попробовать «битые» файлы

Поиск

python catalog.py search "инвертор"
python catalog.py search "цифровая обработка сигналов" -n 30
python catalog.py search stm32 dma --ext pdf
python catalog.py search "операционный усилитель" --lang ru --year-from 2010
python catalog.py search "\"частотное преобразование\""   # точная фраза
python catalog.py search fpga -verilog                    # минус — исключить слово
python catalog.py search can --section datasheet          # только в разделе

Поиск морфологический: слова приводятся к основе, поэтому «инвертор» находит «инверторы» и «инвертора». Ранжирование — BM25 с повышенным весом названия и ключевых слов; в выдаче показывается фрагмент текста с подсветкой.

Свои ключевые слова

Кроме слов, вычисленных из текста, к любому документу можно добавить свои — рубрику, проект, пометку «нужное». Они полноправно участвуют в поиске и даже весят в нём больше вычисленных.

В окне: выбрать документ, вписать слова через запятую в строку «Свои ключевые слова» под карточкой и нажать «Сохранить» (или Enter, или Ctrl+S). При вводе подсказываются слова, уже заведённые в этом каталоге.

В командной строке:

python catalog.py tag opamp "силовая электроника, к проекту А"   # добавить
python catalog.py tag 137 --remove "к проекту А"                 # убрать
python catalog.py tag 137 --set "только это"                     # заменить список
python catalog.py tag 137 --set                                  # очистить
python catalog.py tag 137                                        # показать
python catalog.py tag --all                                      # все слова каталога
python catalog.py search "к проекту А"                           # найти помеченные

Документ указывается номером id или частью имени, пути либо названия.

Слова хранятся отдельно от результатов разбора и привязаны к пути файла, поэтому переживают повторный разбор папки и перестроение каталога. В отчёты они попадают отдельной строкой («Свои ключевые слова»), в HTML-каталоге выделены цветом, в CSV — отдельной колонкой.

Отчёты

После report в папке out/:

  • catalog.html — автономная страница: поиск по мере ввода, фильтры, тезисы и ключевые слова у каждого документа, ссылки на файлы. Открывается двойным щелчком, без сервера;
  • catalog.md — каталог по разделам для чтения и печати;
  • catalog.json, catalog.csv — выгрузка для других программ (CSV с BOM, открывается в Excel).

Как строятся описания и тезисы

Реферирование экстрактивное — фразы берутся из самого документа, ничего не досочиняется:

  1. из файла читаются первые --max-pages страниц, оглавление и метаданные;
  2. слова приводятся к основе (лёгкий стеммер для русского и английского), считаются частоты; слова из названия и оглавления получают больший вес;
  3. по всей библиотеке считается IDF — так отсеиваются слова, общие для всей техлитературы, и остаются характерные именно для этого документа;
  4. ключевые слова — верхние основы по TF-IDF, показанные самой короткой частой словоформой;
  5. тезисы — предложения с наибольшей плотностью ключевых слов, с бонусом началу документа (аннотация, введение) и оборотам вида «рассматривается», «предназначено», this book describes; близкие по составу фразы отбрасываются;
  6. описание — тип издания, язык, объём, темы и первый тезис.

Для сканов без текстового слоя тезисы берутся из оглавления PDF, а если его нет — документ попадает в каталог с пометкой «скан» и описанием по имени файла. Найти такие файлы: python catalog.py stats.

Форматы и внешние утилиты

Разбираются PDF, DJVU, DOC, DOCX, RTF, ODT, CHM, EPUB, FB2, PPT, PPTX, XLS, XLSX, TXT, MD. Обязательна только pymupdf (PDF); дополнительно, если есть в PATH:

  • antiword — качественный разбор старых .doc (иначе грубая выборка строк);
  • djvutxt из DjVuLibre — текстовый слой .djvu (иначе для DJVU остаются только название, число страниц и раздел).

Сборка исполняемого файла

Сборщик один — scripts/build_exe.py; что получится, зависит от системы, на которой идёт сборка: PyInstaller не умеет собирать под чужую платформу. Программу для macOS собирают на Mac, для Windows — на Windows.

Windowsdist\Catalogizer.exe:

BUILD_EXE.bat --setup      # один раз: .venv с PySide6, pymupdf, PyInstaller
BUILD_EXE.bat              # сборка

macOSdist/Catalogizer.app:

chmod +x BUILD_APP.command CATALOG.command   # один раз, после переноса файлов
./BUILD_APP.command --setup                  # один раз: .venv и зависимости
./BUILD_APP.command                          # сборка

Оба сценария можно просто запустить двойным щелчком. Ключи передаются в scripts/build_exe.py: --onedir (папка вместо одного файла, запускается быстрее; в macOS так всегда — .app и есть папка), --console (оставить консоль для traceback), --cli (собрать ещё и консольную программу catalog). После сборки автоматически выполняется самопроверка --check: окно строится целиком и программа выходит.

Иконки генерируются кодом — python scripts/make_icon.py создаёт ico/catalog.ico для Windows и ico/catalog.icns для macOS.

Куда программа кладёт базы и отчёты: в Windows и Linux — рядом с исполняемым файлом, в macOS — в ~/Library/Application Support/Catalogizer, потому что содержимое .app считается неизменяемым.

Что учтено для macOS

  • пути и \?\-префикс применяются только в Windows;
  • «Показать в папке» открывает Finder на файле (open -R), «Открыть документ» — open;
  • ссылки на файлы в HTML-каталоге строятся из абсолютного пути и работают и с /Users/..., и с E:\...;
  • в теме заданы системные шрифты (SF Pro Text, SF Mono) как замена windows-овским;
  • папка по умолчанию — ~/Documents, если жёстко прописанной библиотеки нет;
  • .command-файлы сохранены с переводами строк LF, иначе bash их не примет.

Первый запуск неподписанного .app macOS блокирует: правой кнопкой по Catalogizer.app → «Открыть» → «Открыть» в диалоге. Либо снять карантин: xattr -dr com.apple.quarantine dist/Catalogizer.app.

Устройство

CATALOG.bat             запуск окна в Windows
CATALOG.command         запуск окна в macOS
BUILD_EXE.bat           сборка exe в Windows
BUILD_APP.command       сборка .app в macOS
catalog_gui.py          точка входа окна (её упаковывает PyInstaller)
catalog.py              точка входа командной строки
catalogizer/
    app.py              сборка QApplication, ключ --check
    config.py           папка по умолчанию, форматы, ограничения разбора
    extract.py          чтение PDF, DJVU, DOC(X), RTF, CHM, EPUB, FB2, XLS(X), TXT
    textutil.py         язык, токенизация, стемминг, разбиение на предложения
    summarize.py        TF-IDF, ключевые слова, тезисы, описание
    scanner.py          обход папки, многопоточное извлечение
    analyze.py          проход анализа по всей базе
    search.py           запросы к полнотекстовому индексу
    report.py           HTML, Markdown, JSON, CSV
    db.py               SQLite + FTS5
    ui/                 тёмная тема, главное окно, вкладки, фоновый поток
scripts/build_exe.py    сборка exe/.app — под ту систему, где запущен
scripts/make_icon.py    генерация иконок .ico и .icns

Замечания по работе

  • Файлы длиннее 260 символов пути читаются через префикс \\?\; PDF передаются MuPDF потоком в память, поэтому нестандартные пути не мешают.
  • Кодировка русских .txt определяется перебором (utf-8, cp1251, koi8-r, cp866).
  • Разбор одного PDF ограничен по времени (PDF_TIME_BUDGET, 25 с): повреждённый файл MuPDF чинит страницу за страницей и может занять минуты.
  • Сбой на файле не останавливает обход: причина сохраняется в поле error и видна в stats. Файл, трижды оборвавший разбор, дальше пропускается — вернуть его в очередь можно ключом --retry-broken.
  • Если папка лежит под управлением клиента синхронизации (Яндекс.Диск, OneDrive), его драйвер может надолго придерживать открытые файлы. На время первого разбора синхронизацию лучше приостановить.
Description
No description provided
Readme 89 KiB
Languages
Python 95.5%
Batchfile 2.6%
Shell 1.9%