Bot for monitoring the results of the Unified State Exam from a regional resource. Pet-project in 24 hours

Good afternoon everyone!

This year I am an 11th grade graduate and, accordingly, a person who takes the Unified State Exam. The exam results usually come no earlier than a week later. At the same time, they can be tracked on at least 3 resources: Gosuslugi, Checkege (a single portal) and on the websites of regional information processing centers – RCOI. The trend of recent years shows that the results appear on regional resources first.
Therefore, while I was in agonizing anticipation, I decided to analyze the website of the Perm Region Regional Center for Occupational Health and Safety. It is important to note that these websites differ in each region, so there is no universal recipe here, no documentation for developers or public API, especially.

Form for requesting results

Form for requesting results

To obtain the exam results, you only need to know the series and number of your passport. After entering them, the results are presented in the form of an impersonal table.

Table with results

Table with results

I was pleased by the absence of captchas and any anti-fraud systems on the site, this will certainly make the task easier.

Let's get started

First, I found a PHP script that would pass the examinee's passport number and series, but when I tried to simply pass the data, I got the error “Session not created”. It turns out that the passport data entry page generates some “rhash” that needs to be passed in the script parameters, and each such generated hash can only be used once, otherwise we risk getting the error “Session not active”.

Since I decided to develop the bot in Python, the requests were tested immediately using the requests library.

>>> params = {'rhash': '581db7b0f8dd2ed7482c7674b49f1bea5ff6d806978f', 'ds':'', 'dn':''}
>>> r = requests.get('https://kraioko.perm.ru/utils/results/loadstudentresults.php', params=params)
>>> r.text
<table width=100%>\r\n <tr bgcolor=linen class=headline>\r\n            <td>Предмет\r\n            <td>Тестовый балл\t\t\t\r\n            <td>Результат\r\n            <td>Год<tr bgcolor=white><td><a id='id5CD1D809-54C4-4CBF-8CEF-ADE985B98146'>Русский язык</a><td>93\r\n        <td>Экзамен сдан\r\n        <td>2023
длинный и малочитамемый код таблицы

That's it, the necessary data was obtained. Next, I parsed it using classic tools – BeautifulSoup4 and lxml.
As a result, the table was packed into this easy-to-read form:

[['Русский язык', '93', 'Экзамен сдан', '2023'], ['Математика', '90', 'Экзамен сдан', '2024'], ['Информатика', '93', 'Экзамен сдан', '2024']]

The most non-trivial task of this project has been solved, now it remains to create a bot using aiogram and add a sqlite3 database to store user data.

Telegram Bot

Immediately after launching the bot, the user needs to save passport data, then obtaining results is reduced to entering one command /check. To maintain confidentiality, despite the fact that only 10 digits from the passport are saved, the user's Telegram ID is hashed and added to the database table in this form. When requesting results, the user ID is hashed and the passport data is requested based on this hash value.

List of results received from the bot

List of results received from the bot

Receiving results is now available, the most important thing remains – monitoring results and notifications about their changes on the site. For this, we had to sacrifice confidentiality, because an exact comparison of “User and his Chat ID – Passport data” is necessary in order to send changes if they appear.
To avoid storing the full list of results for each user in the database, I decided to hash this data with SHA-256 and store this value in a table (initially I used the length of the resulting table as a marker for changes, but it became obvious that subject scores could be changed without adding new rows).
Then I wrote an asynchronous function that receives the results, hashes them and compares them with the stored value in the database. When changes occur, the hash is rewritten and the user receives a notification. The function is executed once every 10 minutes, but this value can be changed by the bot administrator without restarting (several admin commands were implemented).

Notification of results change

Notification of results change

Team for monitoring

Team for monitoring

Deployment and Integration

Next, I created a Dockerfile and used my existing Jenkins pipeline template to deploy it all on a small home server with a local Gitea instance. Of course, not all the functionality of the resource was adapted (for example, the ability to view the score for tasks of a specific exam), but it is enough that users can now be among the first to receive notifications about the results.

The main functionality of the bot (including monitoring of results) was implemented in one day. Later, before publication, the code was refactored and divided into files :).

Repository: https://github.com/gberdyshev/KraiokoPerm_bot
Bot: https://t.me/kraioko_results_bot

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *