Разработка скрипта для обхода Geetest CAPTCHA на Python: от идеи до реализации

Введение – почему распознавание Geetest CAPTCHA кардинально отличается от нового Haval

В современном мире китайские товары и сервисы нашли своё применение практически во всех отраслях. Когда слышишь, что речь идёт о китайской разработке, невольно всплывают в памяти культовые 90-е ролики типа «Очки н-н-надо?». В большинстве случаев, несмотря на ностальгическую улыбку, многое остаётся по-прежнему – как, например, DeepSeek, который так и не стал ни по-настоящему глубоким, ни по-своему поисковым. Однако с Geetest ситуация иная: компания сумела создать систему, которая вызывает немало сложностей у оптимизаторов, вынуждая их переживать моменты отчаяния в попытках обойти капчу.

Разработка скрипта для обхода Geetest CAPTCHA на Python: от идеи до реализации

Почему же китайские разработчики так усердно отказались от автопрома и посвятили себя защите от спама? Существует мнение (конечно, субъективное, но всё же важное), что для GeeTest важны не только внешние рынки, но и внутренний, где они умеют создавать действительно качественные решения. Согласно официальному определению, Geetest CAPTCHA представляет собой современную систему защиты, применяемую на ряде веб-ресурсов для предотвращения автоматизированных запросов. Основу её работы составляет динамический слайдер с пазлом, в котором пользователь должен переместить фрагмент изображения в нужное место.

Мне стало интересно глубже разобраться в механизмах этой капчи, выявить потенциальные подводные камни, которые могут возникнуть при её обходе, и обозначить ключевые моменты, на которые стоит обратить внимание при разработке решателя капчи. Для демонстрации обхода я использую исключительно сервис распознавания (лично я предпочитаю 2Captcha).

Принципы работы Geetest CAPTCHA – решение, которое удивит даже опытного разработчика

Geetest CAPTCHA работает по принципу двухуровневой защиты, где основной элемент – это слайдер-пазл, который включает в себя следующие компоненты:

Динамическая генерация изображений

При каждом новом запросе сервер формирует уникальный фон с «дыркой» и соответствующим фрагментом пазла. Такой подход исключает возможность применения заранее подготовленных решений, поскольку каждая капча формируется индивидуально.

Интерактивный слайдер

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

  • Конечное положение элемента: где именно был размещён пазл;

  • Маршрут перемещения: траектория, по которой двигался слайдер;

  • Временные интервалы: задержки между отдельными действиями пользователя.

Помимо этого, система ведёт сбор и анализ поведенческих данных – этот функционал интегрирован в процесс распознавания и отслеживает даже мельчайшие нюансы движения мыши, естественные колебания курсора и другие неуловимые детали. После завершения операции браузер отправляет все собранные данные на сервер для проверки их соответствия ожидаемому шаблону. Такой многоступенчатый механизм значительно затрудняет имитацию действий реального пользователя и делает автоматический обход Geetest CAPTCHA крайне сложной задачей.

Стоит отметить, что описанный механизм характерен для четвертой версии Geetest (GeeTest V4), в то время как у предыдущей версии (GeeTest V3) отсутствовала возможность работы в «невидимом» режиме, а анализ поведенческих данных был менее сложным. Таким образом, вне зависимости от того, о какой версии идёт речь, обе они представляют собой серьёзное испытание для автоматизаторов – и их обход сложнее, чем, например, решение рекапчи (что, к счастью, не так распространено в Европе).

Особенности Geetest CAPTCHA – почему автоматическое решение этой капчи представляет особую сложность

При работе с reCAPTCHA, как правило, необходимо просто найти на странице несколько статичных параметров, передать их на сервис распознавания и дождаться ответа. Благодаря тому, что эти параметры не меняются, процесс относительно прост. Конечно, могут возникнуть дополнительные сложности, но в целом – всё предсказуемо и прозрачно.

Разработка скрипта для обхода Geetest CAPTCHA на Python: от идеи до реализации

С Geetest ситуация обстоит иначе. Здесь приходится работать как со статикой, так и с динамическими параметрами, которые обновляются при каждом новом отображении капчи. Рассмотрим различия между GeeTest V3 и V4.

GeeTest V3

Для корректного решения капчи в версии V3 требуются следующие элементы:

  • Статичные параметры:

- websiteURL: адрес страницы, на которой размещена капча;

- gt: серверное значение, необходимое для валидации.

  • Динамический параметр:

- challenge: значение, генерируемое при каждой загрузке страницы. Его нужно получать заново для каждой сессии, иначе капча будет считаться недействительной.

GeeTest V4

В данной версии вместо отдельных параметров gt и challenge используется единый объект initParameters, который обязательно содержит:

  • captcha_id: уникальный идентификатор конфигурации капчи для конкретного сайта.

С технической точки зрения всё выглядит довольно просто, однако важно помнить, что данные параметры не находятся непосредственно в HTML-коде страницы, а генерируются только после начала взаимодействия с капчей. Это означает, что помимо их поиска, необходимо эмулировать действия пользователя, что может вызвать подозрения у системы GeeTest. В таких случаях часто становится необходимым использование прокси-серверов. Каждая новая особенность усложняет процесс обхода, и хотя на тестовой странице сервис может работать без прокси, в реальных условиях их применение может оказаться обязательным.

Подготовка к реализации обхода Geetest CAPTCHA

После краткого обзора технической базы капчи пора переходить к практической части – как же обойти этот механизм защиты. Ниже приведён подробный список необходимых компонентов для разработки решения на Python.

Что потребуется:

  • Python 3: Перейдите на официальный сайт python.org, скачайте установщик для своей операционной системы и следуйте инструкциям, не забыв активировать опцию добавления Python в PATH.

Пакетный менеджер pip: Обычно он устанавливается вместе с Python. Чтобы проверить, выполните в командной строке или терминале команду:

pip --version
  • Библиотеки Python: requests и selenium:Для выполнения HTTP-запросов к API 2Captcha и автоматизации работы с браузером (Chrome) необходимы следующие библиотеки:

- requests: для отправки запросов;

- selenium: для управления браузером и взаимодействия с веб-страницей.

Установите их командой:

pip install requests selenium
  • ChromeDriver: Это отдельное приложение, которое позволяет Selenium управлять браузером Google Chrome. Определите текущую версию Chrome через раздел «О Chrome», затем скачайте соответствующую версию ChromeDriver с официального сайта. Распакуйте архив и либо поместите исполняемый файл в папку, указанную в переменной PATH, либо укажите путь к нему в настройках Selenium в коде:
driver = webdriver.Chrome(executable_path='/путь/до/chromedriver', options=options)
  • API-ключ от сервиса распознавания Geetest CAPTCHA: Этот ключ понадобится для интеграции с 2Captcha, о чём будет рассказано далее.

После подготовки всех компонентов, далее приводится полный текст скрипта. Затем следует подробное описание каждого его этапа.

#!/usr/bin/env python3 import re import time import json import argparse import requests from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # Замените на ваш актуальный API-ключ от 2Captcha API_KEY = "Ваш ключ АПИ" # Эндпоинты для взаимодействия с 2Captcha API CREATE_TASK_URL = "https://api.2captcha.com/createTask" GET_TASK_RESULT_URL = "https://api.2captcha.com/getTaskResult" def extract_geetest_v3_params(html): """ Пытаемся извлечь необходимые параметры для GeeTest V3 (gt и challenge) из HTML-кода страницы. Используем регулярные выражения для поиска этих значений. """ gt_match = re.search(r'["\']gt["\']\s*:\s*["\'](.*?)["\']', html) challenge_match = re.search(r'["\']challenge["\']\s*:\s*["\'](.*?)["\']', html) gt = gt_match.group(1) if gt_match else None challenge = challenge_match.group(1) if challenge_match else None return gt, challenge def extract_geetest_v4_params(html): """ Извлекает параметр captcha_id для GeeTest V4 из HTML. Сначала ищем строку вида: captcha_id=<32 шестнадцатеричных символа>. Если после captcha_id встречаются лишние символы, они отбрасываются. """ match = re.search(r'captcha_id=([a-f0-9]{32})', html) if match: return match.group(1) match = re.search(r'captcha_id=([^&"\']+)', html) if match: captcha_id_raw = match.group(1) captcha_id = captcha_id_raw.split("<")[0] return captcha_id.strip() return None def get_geetest_v3_params_via_requests(website_url): """ Для демонстрационной страницы GeeTest V3 возвращаем статичные параметры, как указано в примерах для PHP, Java и Python. Это помогает избежать ошибок, когда метод split() возвращает весь HTML. """ gt = "f3bf6dbdcf7886856696502e1d55e00c" challenge = "12345678abc90123d45678ef90123a456b" return gt, challenge def auto_extract_params(website_url): """ Определяет, какую версию GeeTest использовать, исходя из URL. Если URL содержит "geetest-v4", работаем с V4 (с использованием Selenium для извлечения captcha_id). Если URL содержит "geetest" (но без -v4), предполагаем GeeTest V3 и получаем статичные параметры. Функция возвращает кортеж: (driver, версия, gt, challenge или captcha_id) """ if "geetest-v4" in website_url: options = Options() options.add_argument("--disable-gpu") options.add_argument("--no-sandbox") driver = webdriver.Chrome(options=options) driver.get(website_url) time.sleep(3) try: wait = WebDriverWait(driver, 10) element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#embed-captcha .gee-test__placeholder"))) driver.execute_script("arguments[0].click();", element) time.sleep(5) except Exception as e: print("Ошибка при инициализации виджета для V4:", e) html = driver.page_source captcha_id = extract_geetest_v4_params(html) return driver, "4", None, captcha_id elif "geetest" in website_url: gt, challenge = get_geetest_v3_params_via_requests(website_url) options = Options() options.add_argument("--disable-gpu") options.add_argument("--no-sandbox") driver = webdriver.Chrome(options=options) driver.get(website_url) return driver, "3", gt, challenge else: return None, None, None, None def create_geetest_v3_task(website_url, gt, challenge, proxyless=True, proxy_details=None): """ Формирует задачу для GeeTest V3 с помощью 2Captcha API. Обязательные параметры: URL сайта, gt и challenge. Если не используются прокси, тип задачи устанавливается как "GeeTestTaskProxyless", иначе – "GeeTestTask". """ task_type = "GeeTestTaskProxyless" if proxyless else "GeeTestTask" task = { "type": task_type, "websiteURL": website_url, "gt": gt, "challenge": challenge } if not proxyless and proxy_details: task.update(proxy_details) payload = {"clientKey": API_KEY, "task": task} response = requests.post(CREATE_TASK_URL, json=payload) return response.json() def create_geetest_v4_task(website_url, captcha_id, proxyless=True, proxy_details=None): """ Создаёт задачу для GeeTest V4 через 2Captcha API. Обязательные параметры: URL сайта, версия (4) и объект initParameters, содержащий captcha_id. """ task_type = "GeeTestTaskProxyless" if proxyless else "GeeTestTask" task = { "type": task_type, "websiteURL": website_url, "version": 4, "initParameters": {"captcha_id": captcha_id} } if not proxyless and proxy_details: task.update(proxy_details) payload = {"clientKey": API_KEY, "task": task} response = requests.post(CREATE_TASK_URL, json=payload) return response.json() def get_task_result(task_id, retry_interval=5, max_retries=20): """ Осуществляет периодический опрос 2Captcha API до получения финального результата. При статусе "processing" функция выводит сообщение и ждёт заданное количество секунд. Если достигнут предел попыток, возвращает сообщение об ошибке. """ payload = {"clientKey": API_KEY, "taskId": task_id} for i in range(max_retries): response = requests.post(GET_TASK_RESULT_URL, json=payload) result = response.json() if result.get("status") == "processing": print(f"Капча ещё не решена, попытка {i+1}") time.sleep(retry_interval) else: return result return {"errorId": 1, "errorDescription": "Превышено время ожидания решения."} def main(): parser = argparse.ArgumentParser( description="Решение GeeTest CAPTCHA с помощью 2Captcha API и автоматическим извлечением параметров" ) parser.add_argument("--website-url", required=True, help="URL страницы с капчей") # Опциональные аргументы для использования прокси parser.add_argument("--proxy-type", help="Тип прокси (http, socks4, socks5)") parser.add_argument("--proxy-address", help="IP-адрес прокси-сервера") parser.add_argument("--proxy-port", type=int, help="Порт прокси-сервера") parser.add_argument("--proxy-login", help="Логин для прокси (если требуется)") parser.add_argument("--proxy-password", help="Пароль для прокси (если требуется)") args = parser.parse_args() proxyless = True proxy_details = {} if args.proxy_type and args.proxy_address and args.proxy_port: proxyless = False proxy_details = { "proxyType": args.proxy_type, "proxyAddress": args.proxy_address, "proxyPort": args.proxy_port } if args.proxy_login: proxy_details["proxyLogin"] = args.proxy_login if args.proxy_password: proxy_details["proxyPassword"] = args.proxy_password print("Загружаем страницу:", args.website_url) driver, version, gt, challenge_or_captcha_id = auto_extract_params(args.website_url) if driver is None or version is None: print("Не удалось загрузить страницу или извлечь параметры.") return print("Определена версия GeeTest:", version) if version == "3": if not gt or not challenge_or_captcha_id: print("Ошибка извлечения параметров gt и challenge для GeeTest V3.") driver.quit() return print("Используем параметры для GeeTest V3:") print("gt =", gt) print("challenge =", challenge_or_captcha_id) create_response = create_geetest_v3_task( website_url=args.website_url, gt=gt, challenge=challenge_or_captcha_id, proxyless=proxyless, proxy_details=proxy_details ) elif version == "4": captcha_id = challenge_or_captcha_id if not captcha_id: print("Ошибка извлечения captcha_id для GeeTest V4.") driver.quit() return print("Используем captcha_id для GeeTest V4:", captcha_id) create_response = create_geetest_v4_task( website_url=args.website_url, captcha_id=captcha_id, proxyless=proxyless, proxy_details=proxy_details ) else: print("Неопределённая версия:", version) driver.quit() return if create_response.get("errorId") != 0: print("Ошибка при создании задачи:", create_response.get("errorDescription")) driver.quit() return task_id = create_response.get("taskId") print("Задача успешно создана. Task ID:", task_id) print("Ожидаем решения капчи...") result = get_task_result(task_id) if result.get("errorId") != 0: print("Ошибка при получении результата:", result.get("errorDescription")) driver.quit() return solution = result.get("solution") print("Капча решена. Полученное решение:") print(json.dumps(solution, indent=4)) # Внедряем полученные данные на страницу if version == "3": # Для GeeTest V3 ожидаются поля: challenge, validate, seccode js_script = """ function setOrUpdateInput(id, value) { var input = document.getElementById(id); if (!input) { input = document.createElement('input'); input.type = 'hidden'; input.id = id; input.name = id; document.getElementById('geetest-demo-form').appendChild(input); } input.value = value; } setOrUpdateInput('geetest_challenge', arguments[0]); setOrUpdateInput('geetest_validate', arguments[1]); setOrUpdateInput('geetest_seccode', arguments[2]); document.querySelector('#embed-captcha').innerHTML = '<div style="padding:20px; background-color:#e0ffe0; border:2px solid #00a100; font-size:18px; color:#007000; text-align:center;">' + 'Капча успешно пройдена!<br>' + 'challenge: ' + arguments[0] + '<br>' + 'validate: ' + arguments[1] + '<br>' + 'seccode: ' + arguments[2] + '</div>'; """ challenge_sol = solution.get("challenge") validate_sol = solution.get("validate") seccode_sol = solution.get("seccode") driver.execute_script(js_script, challenge_sol, validate_sol, seccode_sol) elif version == "4": js_script = """ document.querySelector('#embed-captcha').innerHTML = '<div style="padding:20px; background-color:#e0ffe0; border:2px solid #00a100; font-size:18px; color:#007000; text-align:center;">Капча V4 успешно пройдена!</div>'; """ driver.execute_script(js_script) print("Результат внедрён в страницу. Браузер останется открытым 30 секунд для визуальной проверки.") time.sleep(30) driver.quit() if __name__ == "__main__": main()

Описание работы скрипта

Импорт библиотек и установка констант

Импорт модулей:

Скрипт использует стандартные библиотеки Python:

  • re для работы с регулярными выражениями;

  • time для управления задержками;

  • json для форматирования данных;

  • argparse для обработки параметров командной строки;

  • requests для отправки HTTP-запросов. Для автоматизации браузера применяется Selenium с необходимыми классами для настройки опций Chrome, ожидания элементов и взаимодействия с ними.

Константы: Устанавливаются ключ API от 2Captcha (API_KEY) и URL-адреса для создания задачи (CREATE_TASK_URL) и получения результата (GET_TASK_RESULT_URL). Эти параметры являются основой для взаимодействия с сервисом 2Captcha.

Функции для извлечения параметров капчи

extract_geetest_v3_params(html): Функция анализирует HTML-код страницы с использованием регулярных выражений для поиска значений параметров gt и challenge, необходимых для GeeTest V3. Если нужные строки найдены, возвращаются их значения.

extract_geetest_v4_params(html): Функция ищет в HTML параметр captcha_id для GeeTest V4. Сначала она пытается найти 32 шестнадцатеричных символа, а при неудаче использует альтернативный шаблон, корректируя результат.

auto_extract_params(website_url): Эта функция определяет, какую версию GeeTest использовать, исходя из URL страницы. Если в URL присутствует «geetest-v4», используется V4 с Selenium для извлечения captcha_id; если же URL содержит «geetest» (без -v4), предполагается GeeTest V3 с получением статичных параметров через GET-запрос. Функция возвращает объект драйвера, версию, а также параметры (gt и challenge для V3 или captcha_id для V4).

Создание задач для решения капчи через 2Captcha API

create_geetest_v3_task(website_url, gt, challenge, proxyless, proxy_details): Функция формирует JSON-пакет с типом задачи (либо "GeeTestTaskProxyless", если прокси не используются, либо "GeeTestTask" – если используются), включающий URL страницы, gt и challenge. После чего отправляется POST-запрос к API 2Captcha, и возвращается JSON-ответ.

create_geetest_v4_task(website_url, captcha_id, proxyless, proxy_details): Аналогичным образом создаётся задача для GeeTest V4 с указанием версии (4) и объектом initParameters, содержащим captcha_id.

get_task_result(task_id, retry_interval, max_retries): Эта функция осуществляет циклический опрос API 2Captcha, передавая task_id и API-ключ, до получения результата. При статусе «processing» выводится сообщение, и функция ожидает заданный интервал, повторяя запрос до истечения максимального количества попыток.

Основной алгоритм работы (функция main)

1. Парсинг параметров командной строки: С помощью argparse обрабатывается обязательный параметр --website-url и опциональные настройки для прокси (--proxy-type, --proxy-address, --proxy-port, --proxy-login, --proxy-password).

2. Настройка прокси: Если параметры прокси указаны, устанавливается соответствующий режим и формируется словарь proxy_details, иначе режим proxyless остаётся активным.

3. Извлечение параметров капчи: Выводится сообщение о загрузке страницы, затем вызывается функция auto_extract_params, которая возвращает объект Selenium-драйвера, версию капчи и необходимые параметры (gt и challenge для V3 или captcha_id для V4). Если извлечение не удалось, выводится сообщение об ошибке и скрипт прекращает выполнение.

4. Создание задачи на решение капчи: В зависимости от версии GeeTest происходит проверка наличия необходимых параметров и вызывается соответствующая функция (create_geetest_v3_task для V3 или create_geetest_v4_task для V4). Если версия не определена, выполнение прекращается.

5. Обработка ответа от 2Captcha: Если API возвращает ошибку (проверка errorId), выводится сообщение об ошибке и происходит завершение работы браузера. При успешном создании задачи выводится task_id, после чего начинается опрос API для получения результата.

6. Получение и вывод решения: После получения решения капчи оно выводится в отформатированном виде (с помощью json.dumps).

7. Внедрение решения на страницу: С помощью метода driver.execute_script осуществляется внедрение полученных данных:

- Для GeeTest V3 создаются или обновляются скрытые поля формы (geetest_challenge, geetest_validate, seccode), а содержимое элемента #embed-captcha заменяется на сообщение об успешном прохождении капчи с отображением параметров.

- Для GeeTest V4 содержимое элемента заменяется на сообщение о прохождении капчи.

8. Задержка и завершение работы: После внедрения решения скрипт ждёт 30 секунд для визуальной проверки результата и затем закрывает браузер.

9. Планы на будущее: В дальнейшем планируется протестировать решение с помощью сервиса SolveCaptcha для сравнения результатов.

Заключение

В данной статье детально рассмотрены принципы работы Geetest CAPTCHA, а также продемонстрировано, что обход этой сложной системы возможен даже при базовых навыках программирования на Python. Главное – внимательно извлекать все необходимые параметры, так как малейшая неточность может привести к тому, что вам придётся часами возиться с постоянно меняющимся Challenge. Данная методология, подкреплённая использованием сервиса 2Captcha, позволит создать надёжное решение для обхода Geetest CAPTCHA, что делает её особенно привлекательной для специалистов в области SEO и автоматизации.

Ниже представлена запись экрана, демонстрирующая успешное выполнение скрипта, что подтверждает его работоспособность в реальном времени.

Начать дискуссию