Разработка скрипта для обхода Geetest CAPTCHA на Python: от идеи до реализации
Введение в предмет - или почему распознавание капчи Geetest не похоже на новый Haval?
В последнее время китайские товары и сервисы можно встретить практически в любой нише. Да, когда ты слышишь, что это китайская разработка, с улыбкой вспоминаешь 90-е и знаменитые ролики в интернете “Очки н-н-надо?”, и в большинстве случаев мало что изменилось, даже вон DeepSeek по итогу получился не совсем Deep и не до конца Seek. Но кое-что у них все же получилось, и получилось так, что многие оптимизаторы глотают соленые слезы, пытаясь обойти Geetest капчу.
Почему же китайские братушки так сильно забили на импротный автопром, и так сильно заморочились с сервисом для защиты от спама? Есть мнение (оно конечно субъективное, но все же мнение) - просто в случае с GeeTest - его юзают не только на импорт, но и на внутреннем рынке, а для себя делают они умеют.
Вот официальное определение - Geetest CAPTCHA – это современная система защиты, широко применяемая на различных веб-сервисах для предотвращения автоматизированных запросов. В основе её работы лежит динамичный слайдер с пазлом, где пользователю требуется перетащить фрагмент изображения в нужное место.
Мне стало интересно разобраться в этой капче подробнее и описать некоторые подводные камни, которые могут встретиться при ее обходе, и на что следует обратить внимание при написании капча решателя.
Давайте разбираться более подробно.
Сразу небольшая ремарка - обходить Geetest CAPTCHA я буду исключительно через сервис распознавания капчи (я использую 2капча)
Принципы работы Geetest CAPTCHA - решение капчи Geetest, которое растрогает даже видавшего виды разработчика
Geetest CAPTCHA представляет собой двухкомпонентную защиту - собственно сама капча слайдер, которая включает в себя:
Динамическую генерацию изображений.При каждом запросе сервер генерирует уникальный фон с «дыркой» и изображение-пазл. Это усложняет применение заранее подготовленных решений.
Интерактивный слайдер.Пользователь должен перетащить пазл так, чтобы он совпал с вырезанной областью. При этом система фиксирует:
- Конечное положение пазла.
- Траекторию движения слайдера.
- Временные интервалы между действиями.
Второй компонент защиты - сбор и анализ поведенческих данных, в целом этот компонент не существует отдельно от капчи, он действует на всех этапах распознавания: Как пользователь двигал мышкой, как происходило перетаскивание, дрожание курсора и т.п. мелкие детали, на которые не всегда обращаешь внимание.
Ну и наконец - валидация сервером.
После завершения перетаскивания браузер отправляет на сервер данные о движении и позиционировании, которые сравниваются с ожидаемыми параметрами.
Такой многоуровневый подход позволяет усложнить имитацию действий робота и усложнить автоматический обход Geetest капчи.
Описанная выше технология характерна для 4-ой версии Geetest (GeeTest V4), тогда как у его младшего собрата Geetest v3 отсутсвовала возможность проведения проверки в «невидимом» режиме, и была более простая система поведенческого анализа.
По факту же, что 4, что 3 версии Geetest капчи не особо просты для автоматизаторов, и хуже поддаются обходу, чем та же рекапча (благо гитест не так распространен в Европе).
Особенности Geetest CAPTCHA в чем тонкости и почему решить эту капчу на автомате не самая простая задача?
Для распознавания, скажем, reCAPTCHA, требуется отыскать на странице, где расположена капча определенные параметры, передать их на сервис распознавания капчи и дождаться решения. Причем эти параметры не динамические, а статические. Статика сильно облегчает процесс распознавания. Да, есть другие параметры, которые могут осложнить жизнь, при распознавании reCAPTCHA, но на уровне найти на странице и передать на сервис, все вполне себе прозаично.
С Geetest CAPTCHA не все так однозначно… Там есть и старая добрая статика и динамика, которую нужно находить каждый раз, когда меняется капча.
Рассмотрим на примере Geetest v3 и Geetest v4
Geetest v3
- статичные параметры, которые требуются для корректного распознавания капчи:
websiteURL – URL страницы с капчей.
gt – значение.
Динамический параметр:
challenge – генерируется при загрузке страницы (его необходимо получать каждый раз заново, иначе капча будет считаться недействительной).
Geetest v4
Вместо отдельных параметров gt и challenge тут используется объект initParameters, который обязательно должен содержать captcha_id – идентификатор конфигурации капчи для сайта.
С технической точки зрения, вроде как все просто, но не забываем о том, что все эти параметры находятся не html странице, где расположена капча, а генерятся после того, как с капчей начинают взаимодействовать, то, есть дополнительно к поиску нужных параметров, подключается необходимость эмуляции действий пользователя, что в свою очередь может стать красным флагом для GeeTest, так что тут в большинстве случаев могут потребоваться прокси.
В общем, каждая новая необходимость, тянет за собой еще одну и еще одну. Я буду пробовать обойти GeeTest CAPTCHA на тестовой странице сервиса, там не сильно она сложная и должно все получится без прокси, но не забывайте, что они могут понадобиться вам.
Подготовка к реализации обхода капчи Geetest
Краткий экскурс в техническую составляющую капчи я провел, пора переходить к основной части - как же ее обойти.
Для начала нудное введение, что нужно для обхода Geetest CAPTCHA:
Python 3
- Зайдите на официальный сайт python.org и скачайте установщик для вашей операционной системы.
- Следуйте инструкциям установщика, убедившись, что опция добавления Python в PATH активирована.
Пакетный менеджер pip
pip обычно устанавливается вместе с Python.
Как проверить:Откройте командную строку (или терминал) и выполните команду:
Необходимые библиотеки Python: requests и selenium
- Что нужно: Две внешние библиотеки: - requests – для выполнения HTTP-запросов к API 2Captcha. - selenium – для управления браузером (Chrome) и автоматизации взаимодействия с веб-страницей.
Как установить:
Выполните в командной строке:
ChromeDriver
ChromeDriver – это отдельное приложение, которое позволяет Selenium управлять Google Chrome.
Как установить:
- Определите версию Chrome: В браузере откройте меню «О Chrome» (обычно в разделе «Справка» или «О программе») и узнайте текущую версию браузера.
- Скачайте соответствующую версию ChromeDriver: Перейдите на официальный сайт ChromeDriver и скачайте версию, которая соответствует вашей версии Chrome.
- Настройте PATH: Распакуйте скачанный архив и поместите исполняемый файл chromedriver в папку, которая находится в системной переменной PATH. Либо укажите путь к нему в настройках Selenium в коде, например:
Еще понадобится ключ АПИ от сервиса распознавания GeetTest CAPTCHA, ниже расскажу куда его нужно будет подставить.
Сразу приведу полный текст скрипта, а уже ниже опишу что он делает и как:
Что делает скрипт:
Импорт библиотек и определение констант:
- Импорт модулей: Скрипт использует стандартные модули Python — re для работы с регулярными выражениями, time для задержек, json для форматирования данных, argparse для обработки аргументов командной строки, а также requests для отправки HTTP-запросов. Для автоматизации браузера применяется библиотека Selenium с импортом необходимых классов (например, для настройки опций Chrome, ожидания элементов и работы с элементами страницы).
- Константы: Определён API-ключ 2Captcha (API_KEY) и URL-адреса API для создания задачи (CREATE_TASK_URL) и получения результата (GET_TASK_RESULT_URL). Эти параметры используются для взаимодействия со службой 2Captcha.
Функции для извлечения параметров капчи:
- extract_geetest_v3_params(html): Принимает HTML-код страницы и с помощью регулярных выражений пытается найти значения параметров gt и challenge, которые требуются для GeeTest V3. Если соответствующие строки найдены, функция возвращает их значения.
- extract_geetest_v4_params(html): Извлекает параметр captcha_id для GeeTest V4. Сначала пытается найти строку, содержащую 32 шестнадцатеричных символа после метки captcha_id. Если это не удаётся, используется альтернативный шаблон с последующим отбрасыванием лишних символов.
Автоматическое определение версии капчи и извлечение параметров (auto_extract_params):
Функция получает URL страницы и определяет, какую версию GeeTest использовать:
- GeeTest V4:
Если URL содержит подстроку "geetest-v4", то скрипт:
- Инициализирует браузер Chrome с отключённым GPU и в режиме без песочницы.
- Загружает страницу.
- Использует WebDriverWait для ожидания появления элемента с CSS-селектором #embed-captcha .gee-test__placeholder.
- Выполняет клик по элементу, чтобы инициировать загрузку капчи.
- Ждёт несколько секунд для загрузки виджета.
- Получает исходный HTML и извлекает captcha_id с помощью функции extract_geetest_v4_params.
- Возвращает объект драйвера, версию "4", значение для gt (в данном случае None) и извлечённый captcha_id.
- GeeTest V3:
Если URL содержит подстроку "geetest" (но не "geetest-v4"), то:
Получаются статичные параметры gt и challenge с помощью функции get_geetest_v3_params_via_requests.
Инициализируется браузер Chrome с аналогичными настройками.
Загружается страница.
Возвращается драйвер, версия "3", а также значения gt и challenge.
- Если ни одно условие не выполнено, функция возвращает None для всех значений.
Создание задач для решения капчи через 2Captcha API:
- create_geetest_v3_task(website_url, gt, challenge, proxyless=True, proxy_details=None): Формирует JSON-пакет с типом задачи. Если не используется прокси, тип задачи — "GeeTestTaskProxyless", иначе — "GeeTestTask". В пакет включаются обязательные параметры: URL страницы, gt и challenge. Дополнительно можно передать данные о прокси, если они указаны. После формирования запроса выполняется POST-запрос к API 2captcha для создания задачи, и возвращается ответ в формате JSON.
- create_geetest_v4_task(website_url, captcha_id, proxyless=True, proxy_details=None): Аналогичным образом формируется задача для GeeTest V4. Отличительной особенностью является указание версии (число 4) и вложенного словаря initParameters, содержащего captcha_id.
Функция опроса результата (get_task_result):
Функция отправляет периодические POST-запросы к 2captcha API (на адрес GET_TASK_RESULT_URL), передавая идентификатор задачи (task_id) и API-ключ.
Если в ответе статус равен "processing", функция выводит сообщение о том, что капча ещё не решена, и ждёт указанное время (по умолчанию 5 секунд) перед следующим запросом.
Если получен иной статус (например, готовое решение), возвращается результат.
После исчерпания максимального количества попыток возвращается сообщение об ошибке (timeout).
Основная функция main:
- Парсинг аргументов командной строки: Используется модуль argparse для обработки обязательного параметра --website-url (URL страницы с капчей) и опциональных параметров для настройки прокси (--proxy-type, --proxy-address, --proxy-port, --proxy-login, --proxy-password).
Настройка работы с прокси: Если указаны параметры прокси, переменная proxyless устанавливается в False и формируется словарь proxy_details с соответствующими данными. Если прокси не используются, proxyless остаётся True.
Извлечение параметров капчи: Выводится сообщение о загрузке страницы, затем вызывается функция auto_extract_params, которая возвращает:
- Объект драйвера Selenium (для управления браузером).
- Версию капчи ("3" или "4").
- Для V3 – значения gt и challenge, для V4 – значение captcha_id.
- Если драйвер или версия не получены, выводится сообщение об ошибке и выполнение прерывается.
- Создание задачи на решение капчи:
В зависимости от версии:
- Для GeeTest V3: Проверяется наличие значений gt и challenge. Затем выводятся параметры, и вызывается функция create_geetest_v3_task.
- Для GeeTest V4: Проверяется наличие captcha_id. Выводится значение и вызывается функция create_geetest_v4_task.
- Если версия не распознана, скрипт завершает работу.
- Обработка ответа от 2captcha: Если API возвращает ошибку (проверка errorId), выводится сообщение об ошибке, браузер закрывается, и выполнение завершается.Если задача успешно создана, выводится task_id, и начинается ожидание решения капчи через функцию get_task_result.
- Получение и вывод решения капчи: После успешного получения результата (решение капчи) оно выводится в формате отформатированного JSON.
- Внедрение решения в страницу через JavaScript: С помощью метода driver.execute_script в зависимости от версии выполняется:
- Для GeeTest V3:
- Создаются (или обновляются) скрытые поля формы с идентификаторами geetest_challenge, geetest_validate и geetest_seccode с соответствующими значениями из решения.
- Обновляется содержимое элемента с идентификатором #embed-captcha, выводя сообщение об успешном прохождении капчи с отображением параметров.
- Для GeeTest V4: Простой скрипт заменяет содержимое элемента #embed-captcha сообщением об успешном прохождении капчи.
- Задержка и завершение работы браузера: После внедрения решения в страницу скрипт ожидает 30 секунд (для визуальной проверки результата) и затем закрывает браузер.
В скором времени хочу еще потестить SolveCaptcha - посмотреть как они справляются с распознаванием.
Таким образом, скрипт выполнен так, чтобы можно было визуально увидеть, что капча решена. Ниже привожу запись экрана, как у меня отработал этот скрипт.
Заключение
В данной статье я подробно рассмотрел принципы работы Geetest CAPTCHA и даже попытался показать, что обойти ее можно, даже при наличии минимальных навыков в программировании (Python может считаться программированием?).
Но нужно быть максимально внимательным в извлечении всех необходимых параметров, так как можно провозиться не один час с каким нибудь динамичным Challenge, как это произошло у меня.