Skip to content
VladSmrPublic

About

KP → IMDB Rating Importer

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

22 Commits

Folders and files

Repository files navigation

KP → IMDB Importer

Статья на хабре - https://habr.com/ru/articles/1089900/

Программа переносит ваши оценки фильмов с Кинопоиска на IMDB. Работает в два простых шага:

  1. Парсинг — собирает ваши оценки с Кинопоиска и сохраняет их в файл.
  2. Проставление — берёт собранные оценки и ставит их на IMDB.

🖥️ Для пользователей (установка и использование)

Эта часть предназначена для обычных пользователей — тех, кто просто хочет перенести свои оценки. Здесь нет технических деталей, только то, что нужно знать для работы.

Что это за программа?

Программа переносит оценки фильмов с Кинопоиска на IMDB. Она делает это сама: вам нужно лишь один раз войти в свои аккаунты и нажать пару кнопок.

Как установить

  1. Перейдите на страницу последнего релиза и скачайте установщик .msi: 👉 Скачать последнюю версию

    На странице релиза найдите asset вида KP IMDB Importer-<версия>.msi (например, KP IMDB Importer-1.0.2.msi) и скачайте его.

  2. Запустите скачанный файл двойным щелчком мыши.

  3. Подтвердите установку, если Windows попросит права администратора (нажмите «Да»).

  4. Дождитесь окончания установки.

Системные требования

  • Windows (7/10/11 и новее).
  • Установленный Google Chrome — программа управляет браузером для входа на Кинопоиск и IMDB.
  • Интернет-соединение.

Как запустить

После установки в меню «Пуск» (и на рабочем столе) появится ярлык «KP IMDB Importer». Нажмите на него — откроется окно программы (версия отображается внизу слева).

Как пользоваться

Внутри программы следуйте шагам на экране:

  1. Выберите «Парсинг» — программа откроет Кинопоиск. Войдите в свой аккаунт Кинопоиска и нажмите Start Parsing. Оценки будут собраны и сохранены.
  2. Выберите «Проставление» — программа откроет IMDB. Войдите в свой аккаунт IMDB и нажмите Start Proset. Оценки будут проставлены.

Во время работы можно ставить процесс на паузу (Pause), продолжать (Continue) или полностью остановить (Stop).

Где хранятся данные

Все файлы программы находятся в папке:

C:\Users\<ваше имя>\KP-IMDB-Importer

Здесь хранятся собранные оценки (kp-ratings-{ID}-{метод}.csv, например kp-ratings-123-api.csv) и служебные файлы (логи, профиль браузера).

Важные предупреждения

  • ⚠️ Не открывайте и не редактируйте файл дампа (kp-ratings-*.csv) во время работы программы. Программа постоянно записывает в него данные, и ручное изменение может привести к потере оценок.
  • ⚠️ Не запускайте «Парсинг» и «Проставление» одновременно. Программа сама запретит второй запуск, пока первый не закончится — дождитесь завершения.
  • ⚠️ Если файл дампа открыт в Excel, программа встанет на паузу — закройте файл и нажмите Continue.

👨‍💻 Для разработчиков

Ниже — техническая информация для тех, кто будет запускать или дорабатывать проект.

Стек

  • Java 21, Spring Boot 3.3.2, Thymeleaf
  • Selenium (управление Chrome), jsoup
  • JavaFX WebView (десктоп-оболочка), jpackage (сборка установщика)
  • Сборка: Maven (wrapper mvnw)

Точки входа

Класс Назначение
ru.importer.notes.NotesApplication Разработка: запуск Spring Boot, UI открывается в браузере по адресу http://localhost:8085/notes.
ru.importer.notes.desktop.DesktopLauncher Десктоп-версия: JavaFX WebView-окно, рендерит тот же UI без адресной строки. Можно запускать из IDE.
ru.importer.notes.desktop.AppLauncher Главный класс для упакованного билда (.exe/.msi). Обходит ограничение JavaFX при запуске с classpath.

Запуск из IDEA / отладка

Точка входа — NotesApplication.main (UI: http://localhost:8085/notes). Для отладки десктоп-окна запустите DesktopLauncher.main — JavaFX-окно само поднимет встроенный сервер на порту 8085.

Запуск тестов

В pom.xml по умолчанию skipTests=true, поэтому без аргументов тесты пропускаются. Запускайте явно:

# Unit-тесты
mvnw clean test -DskipTests=false

# Включая интеграционные тесты (реальные сайты КП/IMDB, отмечены @Tag("integration"))
mvnw test -DskipTests=false -Dgroups=integration

Сейчас в проекте 273 unit-теста; интеграционные тесты в этот счёт не входят.

Сборка десктоп-установщика .msi

Десктоп-версия — это JavaFX WebView-оболочка, которая рендерит тот же Thymeleaf-UI в настоящем окне. Сборка в установщик выполняется через jpackage (входит в JDK 21).

Требования к машине сборки

  • JDK 21 (включает jpackage и jlink).
  • JavaFX 21.0.2 (win-модули в локальном Maven-кэше — уже объявлены в pom.xml).
  • WiX Toolset 3.x — нужен только для --type msi (одноразовая установка, скачать с https://wixtoolset.org/docs/v3/). Без WiX можно собрать только промежуточный app-image, .msi не создастся.

Команды

# 1. Fat-JAR (для разработки)
mvnw clean package -DskipTests=false

# 2. app-image (промежуточная папка target/dist/KP IMDB Importer/)
mvnw package -Pdesktop -DskipTests=false

# 3. .msi (нужен WiX) — результат: target/dist/KP IMDB Importer-<версия>.msi
mvnw package -Pdesktop-msi -DskipTests=false

Либо напрямую скриптом (из корня проекта):

powershell -ExecutionPolicy Bypass -File build-msi.ps1 -Msi

Оба desktop-профиля (desktop, desktop-msi) делегируют фактическую сборку в build-msi.ps1: тонкий jar + app/*, jlink runtime-image с JavaFX, jpackage. Скрипт вызывается с -SkipBuild, т.к. Maven уже собрал thin jar к фазе package.

Непрерывная интеграция (GitHub Actions)

Workflow .github/workflows/build-msi.yml на каждый push в main (и по ручному запуску workflow_dispatch):

  1. Ставит JDK 21 (Temurin) через actions/setup-java (с кешем Maven-репозитория).
  2. Запускает юнит-тесты (mvnw clean test -DskipTests=false).
  3. Ставит WiX Toolset 3.x (choco install wixtoolset) — jpackage находит его автоматически в C:\Program Files (x86)\WiX Toolset v3.14\bin.
  4. Собирает .msi через build-msi.ps1 -Msi (JavaFX win-jar подтягиваются в локальный m2-кеш самой сборкой).
  5. Загружает .msi как build-artifact (сохраняется всегда).
  6. Публикует GitHub Release (вариант B) — только если версия в pom.xml изменилась относительно последнего опубликованного Release. Если версия не менялась — Release не трогается.

Версия для релиза берётся из pom.xml (<version>), тег релиза = версия, asset = KP IMDB Importer-<версия>.msi.

После установки .msi в меню «Пуск» и на рабочем столе появляется ярлык «KP IMDB Importer». По клику открывается десктоп-окно, которое само запускает встроенный сервер и Chrome для Selenium. Пользователю не нужна установленная Java — jpackage включает вырезанный JRE 21.

Иконка приложения подключена: packaging/app.ico (валидный многомерный .ico, перегенерируется скриптом packaging/create-icon.ps1, если исходный файл — PNG). build-msi.ps1 автоматически передаёт --icon packaging/app.ico в jpackage.

Рабочая папка приложения

В установленной версии (десктоп-окно / .msi) программа ставится в Program Files, куда писать нельзя. Поэтому все рабочие файлы по умолчанию хранятся в рабочей папке приложения:

%USERPROFILE%\KP-IMDB-Importer        (например C:\Users\<user>\KP-IMDB-Importer)
├── kp-ratings-{ID}-{метод}.csv         # дамп оценок КП (результат парсинга)
└── chrome-profile\                   # профиль Chrome для Selenium (сессии КП/IMDB)

Пользователь по-прежнему может указать собственную директорию на формах — рабочая папка подставляется только как значение по умолчанию.


🔄 Как это работает

Перенос оценок выполняется двумя независимыми этапами:

  1. «Парсинг» — получение оценок пользователя с Кинопоиска и сохранение их в дамп kp-ratings-{ID}-{метод}.csv.
  2. «Проставление» — чтение дампа и проставление оценок на IMDB.

Этапы запускаются отдельно друг от друга и могут выполняться в разное время: сначала парсинг формирует дамп, затем проставление работает уже только с ним. Одновременный запуск парсинга и проставления запрещён — приложение отклоняет второй запуск, пока первый не завершён.

Этап «Парсинг» (КП → дамп)

Оценки пользователя получаются одним из трёх способов (выбор на странице приложения):

Способ Ключ Что делает Что нужно
API (token) api Быстрый парсинг через kinopoiskapiunofficial.tech без браузера. API отдаёт все оценки пользователя ID пользователя КП, API-токен
Браузер selenium Полный парсинг всех оценок в открытом Chrome (залогиненная сессия), догружает оригинальные названия ID пользователя КП, вход в КП в Chrome
Полный (браузер + API) full Selenium собирает полный список оценок (title/оценка/год/kpId), затем API-обогащение каждого фильма — оригинальное название, год (истина из API), imdbId. Повторный запуск дописывает дельту: новые фильмы и «дефицитные» (нет imdb_id / оригинального названия / невалидный год); удалённые с КП оценки остаются в дампе ID пользователя КП, API-токен, вход в КП в Chrome

Название с «приклеенным» годом зачищается («Мортал Комбат 22025» → «Мортал Комбат 2» + 2025); год проверяется на диапазон 1890–2050: при API — дозапросом данных фильма (ретраи при 429/5xx, троттлинг 600 мс), при Selenium — открытием страницы фильма.

При способе full парсинг выполняется в две фазы: (1) Selenium собирает полный список оценок со страниц выгрузки КП (по 20 фильмов, title/оценка/год/kpId); (2) для каждого фильма вызывается GET /v2.2/films/{id} — возвращает оригинальное название, год (источник истины) и imdbId. При исчерпании дневной квоты API (402 после трёх проверок) этап корректно завершается с сообщением «квота токена на сегодня исчерпана, дамп сохранён, продолжите завтра»; следующий запуск продолжит обогащение с места остановки. Коды 429 и 5xx — ретраи; 401/403 — невалидный токен, парсинг прерывается.

Результат парсинга сохраняется в kp-ratings-{ID}-{метод}.csv (например, kp-ratings-123-api.csv: ID профиля КП + способ парсинга; повторный парсинг тем же способом перезаписывает файл, кроме full — тот дописывает дельту, не удаляя существующие строки). Файл перезаписывается после каждых 5 обработанных фильмов, чтобы статусы появлялись даже при остановке приложения.

Этап «Проставление» (дамп → IMDB)

  • Источник данных — самый свежий по времени изменения файл kp-ratings-*.csv из директории логов (путь указывается на форме); если файлов нового формата нет — старый kp-ratings.csv. Статусы сохраняются в тот же файл.
  • Дубли внутри дампа по kp_id убираются; одинаковый валидный imdb_id у разных названий сбрасывается у обоих (легитимная пара «фильм + сериал» с одинаковым названием не трогается).
  • Фильм с imdb_id открывается напрямую и проверяется (JSON-LD: тип Movie/TVSeries, название, год ±1); чужой тип (подкаст-эпизод, игра) — id сбрасывается, строка идёт в «не найден» без ставки.
  • Поиск по названию и году: при нескольких точных совпадениях названия выбор различается по году (ровно один матч с годом ±1 от года фильма), иначе берётся первый по релевантности; выбранная страница проходит полную верификацию (тип, название, год ±1). Успешная ставка при таком неоднозначном выборе помечается статусом проставлено с оговоркой; не прошла верификацию — «не найден».
  • Результаты: та же оценка — пропущено (уже стоит оценка); другая — руками (оценки отличаются); нет названий или рейтинг 0 — неполные данные (финальный статус); иначе оценка проставляется (успешно) и проверяется повторным чтением.
  • При повторном прогоне «не найден» ретраится как «ошибка» (imdb_id сбрасывается); остальные завершённые статусы пропускаются.
  • Между фильмами пауза 1–2 секунды (имитация пользователя).

Использование

Шаг 0 — выбор этапа

Открыть http://localhost:8085/notes/ — страница-«выбор» с двумя карточками: «Парсинг» и «Проставление».

Парсинг

  1. На странице выбора нажать «Парсинг» → открывается выбор способа (три карточки: API / Браузер / Полный) с пояснением. Выбрать и нажать «Next».
  2. Форма показывает только нужные поля:
    • Браузер — ID пользователя КП и директорию логов;
    • API — дополнительно API-токен;
    • Полный — ID пользователя КП, директорию логов и API-токен.
  3. Если дамп kp-ratings-{ID}-{метод}.csv в указанной директории уже существует — появится предупреждение о перезаписи (подтвердить или вернуться).
  4. Нажать «Next» — откроется Chrome. На странице показывается число оценок на КП (для Браузера и Полного — реальное число, для API — сколько вернул API).
  5. Вручную войти в аккаунт Кинопоиска в открывшемся окне (новая вкладка).
  6. Нажать Start Parsing — парсинг пойдёт в фоне, страница с прогрессом обновится автоматически.
  7. После завершения — страница со статистикой и таблицей по каждому фильму (/parsing-result).

Проставление

  1. На странице выбора нажать «Проставление» → форма, где указывается путь к директории с дампом оценок.
  2. Нажать «Next» — откроется Chrome на imdb.com.
  3. Вручную войти в аккаунт IMDB в открывшемся окне (новая вкладка).
  4. Нажать Start Proset — проставление пойдёт в фоне, страница с прогрессом обновится автоматически.
  5. После завершения — страница со статистикой и таблицей по каждому фильму (/result).

Во время любого этапа

  • Доступны кнопки Pause (пауза после текущего фильма), Continue (продолжить), Stop (полная остановка после текущего фильма; дамп сохраняется).
  • Если файл дампа открыт в Excel, этап встаёт на паузу с подсказкой закрыть файл и нажать Continue.
  • Прогресс и лог видны в реальном времени (SSE) на раздельных страницах прогресса парсинга и проставления.

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


📁 Файлы в директории логов

Файл Описание
kp-ratings-{ID}-{метод}.csv Дамп оценок КП со статусами (имя = ID профиля КП + способ парсинга; примеры: kp-ratings-123-api.csv, kp-ratings-123-full.csv). Способ full дописывает дельту при повторном запуске, не перезаписывая существующие строки. Если файлов нового формата нет, этап «Оценка» читает старый kp-ratings.csv. UTF-8 с BOM, разделитель ;, заголовок title;original_title;english_title;year;rating;kp_id;imdb_id;status;error. Запись атомарная (сначала .tmp, затем rename) — при сбое файл не усекается.

Подробный лог хода процесса пишется в консоль приложения (SLF4J).

Статусы (колонка status в CSV)

Статус Описание
успешно Оценка проставлена на IMDB
проставлено с оговоркой Оценка проставлена при неоднозначной выдаче поиска (несколько точных совпадений названия) — завершённый статус
не найден Фильм не найден на IMDB
пропущено (уже стоит оценка) На IMDB уже стоит такая же оценка
руками (оценки отличаются) На IMDB стоит другая оценка
неполные данные В строке нет названий или рейтинг 0 — считается обработанной
ошибка Произошла ошибка при обработке

Статусы записываются в дамп по ходу проставления. Завершённые (все, кроме «не найден» и «ошибка») при повторном запуске пропускаются.


🏗️ Структура проекта

notes/
├── src/main/java/ru/importer/notes/
│   ├── movie/                          # Processor (оркестратор этапов), ParsingStage (КП → дамп),
│   │                                   # ProsettingStage (дамп → IMDB), KpDumpWriter (запись дампа),
│   │                                   # ProcessCoordinator (запрет параллельных этапов), ImportProgress (SSE)
│   ├── imdb/                           # ImdbNotesExporter (остов этапа), ImdbSearchAndSelect (поиск/выбор),
│   │                                   # ImdbPageVerifier (верификация JSON-LD), ImdbRatingClicker (оценка),
│   │                                   # auth/AuthManager (единственный WebDriver)
│   ├── kp/                             # KpNotesImporter (остов парсинга КП), KpRatingsPageParser,
│   │                                   # GluedYearTitleCleaner (склеенный год), KpYearValidator (1890–2050),
│   │                                   # Selenium/Api/CsvKpRatingsProvider (способы получения оценок)
│   ├── web/MainController.java         # веб-контроллер (маршруты этапов, страница ошибки)
│   ├── desktop/                        # DesktopLauncher (JavaFX WebView-окно), AppLauncher (.exe/.msi)
│   ├── util/                           # WorkingDir (рабочая папка), AppVersionReader (версия в окне),
│   │                                   # ChromeProcessKiller (авто-закрытие своего Chrome), ErrorFormatter
│   ├── log/LogFileService.java         # атомарная запись/чтение дампа (kp-ratings-{ID}-{метод}.csv / kp-ratings.csv)
│   └── dto/                            # модели данных (MovieData: статусы MovieStatus)
├── src/main/resources/templates/       # home, main, method-form, confirm-overwrite, login-kp, login-imdb,
│                                       # importing-parsing, importing-proset, parsing-success, proset-form,
│                                       # success, error
├── packaging/                          # иконка app.ico, скрипт create-icon.ps1
├── build-msi.ps1                       # сборка десктоп-установщика через jpackage
└── pom.xml

Основные маршруты

URL Метод Назначение
/ GET Страница-«выбор» этапа (Парсинг / Проставление)
/main GET Выбор способа парсинга
/method POST Форма данных для выбранного способа парсинга
/submit POST Подготовка парсинга (с проверкой перезаписи дампа)
/submit-confirmed POST Подтверждение перезаписи дампа → открытие браузера КП
/start-parsing POST Запуск этапа «Парсинг»
/parsing-result GET Результат этапа «Парсинг»
/proset GET Форма проставления (путь к дампу)
/proset-submit POST Подготовка проставления (проверка дампа, открытие IMDB)
/start-proset POST Запуск этапа «Проставление»
/result GET Результат этапа «Проставление»
/progress, /log GET SSE: прогресс и лог текущего этапа
/stop, /pause, /resume POST Управление текущим этапом
/change-log-dir POST Смена директории дампа во время паузы «нужен новый путь»
/error GET Страница ошибки (полный стек-трейс в сворачиваемом блоке)

About

KP → IMDB Rating Importer

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages