Бот мониторинга результатов ЕГЭ с регионального ресурса. Пет-проект за 24 часа13.07.2024 16:00
Всем добрый день!
В этом году я являюсь выпускником 11 класса и, соответственно, человеком, который сдает ЕГЭ. Результаты экзаменов обычно приходят не раньше, чем через неделю. При этом их можно отслеживать как минимум на 3 ресурсах: Госуслуги, Checkege (единый портал) и на сайтах региональных центров обработки информации — РЦОИ. Тенденция последних лет показывает, что раньше всего результаты появляются на региональных ресурсах. Поэтому, находясь в томительном ожидании, я решил проанализировать сайт РЦОИ Пермского края. Важно отметить, что в каждом регионе эти сайты различаются, поэтому универсального рецепта здесь нет, никакой документации для разработчиков или публичного API тем более.
Форма для запроса результатов
Для получения результатов экзамена необходимо знать только серию и номер паспорта. После их ввода результаты представляются в виде обезличенной таблицы.
Таблица с результатами
Порадовало отсутствие капч и каких-либо антифрод систем на сайте, это безусловно облегчит задачу.
Приступим
Сначала я нашел PHP-скрипт, которому передаются номер и серия паспорта экзаменуемого, но при попытке просто передать данные была получена ошибка «Сессия не создана». Оказывается, страница ввода паспортных данных генерирует некоторый «rhash», который необходимо передать в параметрах скрипту, при этом каждый такой сгенерированный хеш можно использовать только один раз, иначе мы рискуем получить ошибку «Сессия на активна».
Так как разрабатывать бота я решил на Python, то запросы тестировались сразу с использованием библиотеки requests.
Всё, необходимые данные были получены. Далее я выполнил парсинг с помощью классических инструментов — BeautifulSoup4 и lxml. В результате таблица была упакована в такой удобочитаемый вид:
Самая нетривиальная задача этого проекта была решена, теперь осталось создать бота с использованием aiogram и добавить базу данных sqlite3 для хранения пользовательских данных.
Телеграм Бот
Сразу после запуска бота пользователю необходимо сохранить паспортные данные, затем получение результатов сводится к вводу одной команды /check. Для сохранения конфиденциальности, несмотря на то, что сохраняются только 10 цифр из паспорта, Telegram ID пользователя хешируется и добавляется в таблицу БД именно в таком виде. При запросе результатов происходит хеширование ID пользователя и запрос паспортных данных на основании этого хеш-значения.
Список результатов, полученных от бота
Получение результатов теперь доступно, оставалось самое главное — мониторинг результатов и уведомления об их изменениях на сайте. Ради этого пришлось пожертвовать конфиденциальностью, т.к. необходимо точное сопоставление «Пользователь и его Chat ID — Паспортные данные» для того, чтобы отправить изменения в случае их появления. Чтобы не сохранять в БД полный список результатов для каждого пользователя, я решил хешировать эти данные с помощью SHA-256 и хранить это значение в таблице (изначально я использовал длину полученной таблицы, как маркер для изменений, но стало очевидно, что баллы по предметам могут быть изменены без добавления новых строк). Затем я написал асинхронную функцию, которая получает результаты, хеширует их и сверяет с сохраненным значением в БД. При изменениях хеш перезаписывается, а пользователю приходит уведомление. Функция выполняется раз в 10 минут, но это значение может быть изменено администратором бота без перезапуска (были реализованы несколько админских команд).
Оповещение об изменении результатов
Команда для мониторинга
Развертывание и интеграция
Далее я создал Dockerfile и использовал имеющийся у меня шаблон пайплайна Jenkins, чтобы развернуть это все на небольшом домашнем сервере с локальным инстансом Gitea. Конечно, был адаптирован не весь функционал ресурса (например, возможность просмотра разбалловки по заданиям конкретного экзамена), но достаточно того, что пользователи теперь могут получать уведомления о результатах в числе первых.
Основной функционал бота (в том числе и мониторинг результатов) был реализован за одни сутки. В дальнейшем, перед публикацией, производился рефакторинг кода и разделение его по файлам :).