Как наука о данных помогла мне обновить мой паспорт
Table Of Content
Немного предыстории перед этой историей: как это обычно бывает у аргентинцев, у меня есть второе гражданство - итальянское, которое я унаследовал от своих родителей. Это двойное гражданство очень помогло мне поступить на магистратуру по науке о данных и обществу за рубежом в 2021 и 2022 годах. Благодаря этому привилегию мне не нужна была виза, стоимость обучения была намного ниже (в то время около €12 тыс. для иностранных студентов и всего €2 тыс. для граждан ЕС), и у меня был доступ к другим льготам, таким как студенческие займы.
Но чтобы воспользоваться всеми этими льготами, которые были доступны только гражданам ЕС, мне нужно было предоставить свой итальянский гражданский документ. В течение нескольких месяцев после моего приезда, занимаясь полноценным обучением и работой на неполный рабочий день, я забыл тщательно проверить свой паспорт. В сентябре, когда я подал заявку на стажировку, я обнаружил, что мой итальянский паспорт истекает в ноябре того же года... действительно удобно.
Итальянское посольство в Нидерландах предлагает очень ограниченное количество ежедневных приемов для обновления паспортов, и, как и ожидалось, я не смог получить ни одного приема до даты истечения срока действия. Самый ранний доступный прием был в марте следующего года. Хотя обновление паспорта не было жизненно важным, мне нужен был паспорт для многих процедур и для свободного перемещения по Европе.
Прежде чем погрузиться в отчаяние, мне пришла в голову идея воспользоваться тем, что я узнал в магистратуре и создать инструмент, который поможет мне получить более ранний прием. Учитывая, что система работала подобно обычной онлайн-системе записи на прием, и предполагая, что если кто-то отменит свой прием, он автоматически (или через определенный интервал времени) будет отображаться как доступный, я приступил к проекту.
Задача бота была очень простой: через определенный промежуток времени он открывал веб-браузер, переходил на страницу посольства, входил в систему с помощью моих учетных данных, проверял, есть ли доступные приемы, и бронировал их.
Программирование всего пути, которым должен следовать бот, было довольно простым, но при попытке запустить его возникли проблемы с обнаружением автоматизации и капчей. Поэтому я решил применить некоторые стратегии, такие как случайное время ожидания между каждым вводом букв моего имени пользователя и пароля, а также прокрутка страницы, чтобы имитировать более человеческое поведение. Кроме того, сам процесс бронирования оказался немного сложнее, поэтому я просто позволил боту проверять наличие доступных приемов и, в случае положительного результата, уведомлять меня, чтобы я мог вручную забронировать прием. И, удивительно, это сработало!
Бот был создан на языке Python с использованием Selenium в качестве пакета для парсинга, поскольку в то время он был мне наиболее знакомым, и мне нужно было взаимодействовать с браузером. Код этого бота можно найти на моем github, и я объясню некоторые его основные части.
Начнем с импорта пакетов, которые мы будем использовать, и инициализации драйвера для автоматического управления браузером, с некоторыми параметрами, которые помогут не так легко обнаружить его, и будущими действиями, которые мы будем выполнять в браузере.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
from webdriver_manager.chrome import ChromeDriverManager
import random
import time
chrome_options = Options()
chrome_options.add_argument("start-maximized")
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
driver_path = ChromeDriverManager().install()
driver = webdriver.Chrome(driver_path, options=chrome_options)
actions = ActionChains(driver)
Определяем константы, такие как имя пользователя и пароль для входа, и идентификаторы html-элементов, которые мы будем использовать, такие как поле ввода для имени пользователя, пароля и кнопку "Далее".
# CONSTANTS
USERNAME = "МОЙ ПОЛЬЗОВАТЕЛЬ"
PASSWORD = "МОЙ ПАРОЛЬ"
...
# HTML Elements
EMAIL_ID = "login-email"
PASSWORD_ID = "login-password"
NEXT_PAGE_CLASS = "button.primary.g-recaptcha"
....
Затем мы определяем основные функции. Это основная функция, которую мы будем использовать в основном для доступа к html-элементам, перемещения к ним, щелчка по ним и вставки определенного текста (например, нашего имени пользователя, пароля и т. д.). Она будет нашим основным браузером на странице.
def input_text(element, text_to_input)->None:
for letter in text_to_input:
element.send_keys(letter)
time.sleep(random.random())
def find_element_and_input(element_id,, text_to_input, driver, has_id = True) -> None:
if has_id:
element = driver.find_element(By.ID, element_id)
else:
element = driver.find_element(By.CLASS_NAME, element_id)
actions.move_to_element(element).perform()
element.click()
time.sleep(1)
if text_to_input:
input_text(element, text_to_input)
time.sleep(3)
return
....
И, наконец, наша основная функция, которая фактически проверяет наличие приемов и уведомляет нас, если есть доступные приемы, в данном случае, через уведомление в консоли. Однако мы могли бы сделать так, чтобы она отправляла нам уведомление по электронной почте, отправляла сообщение через телеграмм или писала нам в Slack, чтобы привести несколько примеров.
def check_availability(AVAILABLE_CLASS, NEXT_CLASS, driver, repetitions=0):
available = driver.find_elements(By.CLASS_NAME, AVAILABLE_CLASS)
if len(available) > 0:
print("Есть прием")
elif repetitions > 4:
next = driver.find_element(By.CLASS_NAME, NEXT_CLASS)
next.click
time.sleep(1)
check_availability(driver, AVAILABLE_CLASS, NEXT_CLASS, repetitions + 1)
else:
print("Нет приемов")
Когда скрипт заработал, я преобразовал его в исполняемый файл, используя auto-py-to-exe, и запланировал его запуск несколько раз в день на моем ПК с помощью task scheduler, чтобы он работал автоматически.
Благодаря этому я смог получить прием намного раньше и обновить паспорт вовремя, не проведя ни одного дня с просроченными документами 🥳.
В качестве бонуса, некоторые фотографии моей поездки в Гаагу, когда я пошел делать документы.
Надеюсь, что это послужит мотивацией для мысли о том, как профессиональные знания могут помочь в повседневной жизни.