- HTML 93.7%
- Python 5.6%
- Shell 0.6%
- Swift 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
copyText: синхронный fallback через execCommand внутри жеста, честный тост при неудаче; таблица: .table-wrap, липкая шапка и первый столбец, dvh; iOS: tap-highlight и dvh для лайтбокса |
||
| .vscode | ||
| data | ||
| deploy | ||
| .gitignore | ||
| extract.py | ||
| i18n.py | ||
| index.html | ||
| ocr_callouts.py | ||
| ocr_callouts.swift | ||
| README.md | ||
| requirements.txt | ||
| translate_manual.py | ||
| viewer.py | ||
Mitsubishi EPC — интерактивный каталог запчастей
Статический просмотрщик электронного каталога запчастей Mitsubishi (EPC): схемы, таблицы деталей, кликабельные выноски, поиск по парт-номеру. Пайплайн извлекает данные из PDF-каталогов (проверено на S4Q2, S4S, S3L2): страницы-таблицы, страницы-схемы и числовые указатели определяются автоматически, PDF задаётся аргументом командной строки.
Репозиторий самодостаточен: содержит исходники пайплайна, конфигурацию деплоя
(deploy/) и собранную статику (index.html + data/).
Установка на сервере (VPS: системный Caddy + Tinyauth)
Статический просмотрщик (index.html + data/) раздаётся системным Caddy
(systemd), доступ закрыт логином через Tinyauth
(forward auth). TLS-сертификаты Caddy получает автоматически (Let's Encrypt).
Что нужно заранее
- VPS с публичным IP, открытые порты 80 и 443.
- Поддомен, A-записью на IP VPS, например
epc.lispotris.top. - Caddy, Docker и Tinyauth — если чего-то нет, установщик предложит поставить.
1. Клонировать репозиторий
ssh user@VPS
sudo mkdir -p /opt/pdf_osr && sudo chown "$USER" /opt/pdf_osr
git clone https://git.lispotris.top/ash/mitsubishi_epc.git /opt/pdf_osr
Статика (index.html + data/) уже в репозитории.
2. Запустить установщик
sudo /opt/pdf_osr/deploy/install.sh
Скрипт спросит домен просмотрщика и (опционально) логин/пароль, затем сам: создаст пользователя Tinyauth, сгенерирует конфиг сайта, подключит его к основному Caddyfile и перезагрузит Caddy.
3. Открыть
https://<домен> → редирект на вход Tinyauth; после логина откроется просмотрщик.
Обновление контента
cd /opt/pdf_osr && git pull
Caddy отдаёт файлы с диска, перезагрузка не нужна.
Подробности и заметки по безопасности — в deploy/README.md.
Локальный запуск пайплайна
python3 -m venv .venv
./.venv/bin/python -m pip install -r requirements.txt
# PDF задаётся аргументом (по умолчанию — каталог S4Q2);
# --out позволяет держать результаты разных каталогов раздельно.
./.venv/bin/python extract.py "путь/к/каталогу.pdf" --out data/s4s
./.venv/bin/python ocr_callouts.py --out data/s4s # схемы -> callouts.json (OCR)
./.venv/bin/python viewer.py --out data/s4s # -> viewer.html (открыть в браузере)
Результат (в каталоге --out, по умолчанию data/):
pages.json— структурированные данные;figures/page_*.png— рендеры страниц-схем;callouts.json— координаты номеров-выносок на схемах (OCR);viewer.html— автономный интерактивный просмотрщик.
Единая точка входа (index.html)
Несколько каталогов можно слить в один просмотрщик с селектором двигателя.
В режиме --catalog результат по умолчанию пишется в index.html в корне
проекта — это и есть единая точка входа (открыть в браузере):
./.venv/bin/python viewer.py --catalog data data/s4s data/s3l2
# -> index.html (селектор двигателя в шапке, поиск по текущему двигателю)
Путь вывода можно переопределить флагом --html.
Структура каталога
Типовая структура каталога Mitsubishi (диапазоны зависят от конкретного файла):
| Содержимое | Как определяется |
|---|---|
| вводная часть (обложка, образец, таблица символов) | листы с метками - A3 -, -B1- |
| пары «схема (FIG) + таблица деталей» по группам | заголовок таблицы REF. / PART NO. / MODEL / APPLICABLE |
| числовой указатель деталей | REF + GROUP/GRP и высокая плотность парт-номеров |
Страница-схема — это страница с растровым изображением непосредственно перед таблицей группы; continuation-страницы без заголовка группы наследуют код группы со схемы или с предыдущей таблицы.
Что извлекается
Страница-таблица группы (kind: "parts"): строки деталей с полями
ref_no, item_no, part_no, rp, seq_ng, description,
qty (по моделям 61S/D, Y16/2SD, Y26/2SD, Y36/2SD, Z26/1SD),
serial_from, serial_upto, mr, vrd.
Страница-схема: рендер в PNG + bbox растрового изображения.
Числовой указатель (kind: "index"): part_no → group_no, page, ref_no.
Ключевые находки
- Текст настоящий (не скан): парт-номера, названия, коды групп извлекаются.
- Таблицы восстановлены по координатам слов и вертикальным линиям
(pdfplumber
extract_tableдаёт объединённые ячейки — не используется). - Выноски на схемах «запечены» в растр: на страницах-схемах нет текстовых операторов, весь чертёж — одно изображение. Кликабельные выноски потребуют OCR.
- Номер выноски =
ref_no+item_no(напр. ref 2 + item 01 → выноска201; ref 1 + item 01 →101). Это позволяет связать строку таблицы со схемой без OCR. - Числовой указатель даёт обратный поиск: парт-номер → группа/страница/выноска.
Кликабельные выноски на схемах
Номера на чертежах «запечены» в растр, поэтому их координаты получаются OCR
(системный Vision.framework через хелпер ocr_callouts.swift; внешние
зависимости не нужны). ocr_callouts.py прогоняет все <out>/figures/*.png,
оставляет токены из 1–3 цифр, отсекает шапку/подвал по bbox схемы и пишет
<out>/callouts.json (координаты в долях 0..1, начало — левый верхний угол).
В просмотрщике (viewer.py) поверх картинки схемы строятся прозрачные
hotspot-кнопки по этим координатам:
- клик по номеру → подсветка (flash) и прокрутка к соответствующей строке таблицы деталей;
- наведение подсвечивает пару «выноска ↔ строка» в обе стороны;
- выноски, которых нет на текущей странице (кросс-групповые, напр.
133–144на схеме65-01-03относятся к65-01-04), ищутся на других страницах-таблицах и при клике выполняется переход на нужную группу.
Пересобрать координаты выносок после изменения схем:
./.venv/bin/python ocr_callouts.py --out data/s4s
./.venv/bin/python viewer.py --out data/s4s
Перевод сканированного мануала на русский (OCR + API)
Для сервисных мануалов без текстового слоя (чистые сканы) есть отдельный
пайплайн translate_manual.py: OCR (тот же Vision.framework) → машинный
перевод через API → сборка русского PDF, где перевод накладывается поверх
оригинала. Переводы кэшируются в редактируемом JSON, поэтому их можно
доработать вручную и пересобрать PDF без повторных запросов к API.
# 1) OCR всех страниц -> <workdir>/manual_ocr.json (можно прервать и продолжить)
./.venv/bin/python translate_manual.py ocr --pdf "/path/manual.pdf" --workdir data/manual_ru
# 2) перевод -> <workdir>/manual_translations.json (EN->RU)
export DEEPL_API_KEY="...:fx" # или YANDEX_API_KEY / GOOGLE_API_KEY
./.venv/bin/python translate_manual.py translate --workdir data/manual_ru --provider deepl
# 3) сборка русского PDF -> <workdir>/manual_ru.pdf
./.venv/bin/python translate_manual.py build --pdf "/path/manual.pdf" --workdir data/manual_ru
# всё сразу; --limit N переводит только первые N строк (для пробного прогона)
./.venv/bin/python translate_manual.py all --provider yandex --limit 200
Провайдеры и ключи (env или --key): deepl (DEEPL_API_KEY, free-ключ
оканчивается на :fx), yandex (YANDEX_API_KEY + YANDEX_FOLDER_ID),
google (GOOGLE_API_KEY), mock (без ключа, заглушка [RU] <текст> —
для проверки сборки). Внешние зависимости не нужны: запросы через urllib.
Артефакты в --workdir:
manual_ocr.json— строки с координатами (доли 0..1) по страницам;manual_translations.json— словарьEN -> RU(правьте вручную; повторныйtranslateне трогает уже заполненные строки);manual_ru.pdf— итоговый PDF (оригинал закрыт белой подложкой, перевод вписан шрифтом с кириллицей, кегль подбирается автоматически).
Ограничения прототипа
- Обрабатываются все страницы каталога (авто-детект), а не фиксированный набор.
- Парсер опирается на шаблон колонок (REF / PART / MODEL / APPLICABLE); для каталогов с иным порядком колонок возможны неточности в подписях моделей.
- Строки-продолжения (напр. шайбы с одинаковым
item_no) не имеют своегоref_no/item_no— они сохраняются отдельными строками. - Точность OCR выносок ~95%; нераспознанные/кросс-групповые выноски помечаются
как
inactive.