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

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

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

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

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

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

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

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

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

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

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

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

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

  • Конечное положение пазла: точное место, куда перемещается элемент;

  • Траекторию движения: весь путь, пройденный слайдером;

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

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

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

Особенности Geetest CAPTCHA – почему автоматизация её решения представляет особую проблему

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

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

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:

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

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

    - requests: для работы с HTTP-запросами;

    - 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 = "Ваш ключ АПИ" # URL-адреса API для создания задачи и получения результата от 2Captcha CREATE_TASK_URL = "https://api.2captcha.com/createTask" GET_TASK_RESULT_URL = "https://api.2captcha.com/getTaskResult" def extract_geetest_v3_params(html): """ Извлекает из HTML-страницы необходимые параметры для GeeTest V3: gt и challenge. Применяются регулярные выражения для поиска этих значений. """ 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): """ Ищет в HTML параметр captcha_id для GeeTest V4. Сначала пытается найти строку с 32 шестнадцатеричными символами, после чего отсекает лишнее. """ 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, и параметры получаются методом GET. Возвращает кортеж: (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) и адреса API для создания задачи (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. Если строка содержит «geetest-v4», применяется версия V4 с Selenium для получения captcha_id; если же присутствует «geetest» без V4 – используются статичные параметры для GeeTest V3.

Формирование задач для 2Captcha API

create_geetest_v3_task(website_url, gt, challenge, proxyless, proxy_details): Создаёт JSON-пакет с типом задачи (либо "GeeTestTaskProxyless", если прокси не задействованы, либо "GeeTestTask", если используются) и включает в себя URL, gt и challenge. После чего отправляет POST-запрос на создание задачи и возвращает ответ в формате 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): Осуществляет периодический опрос 2Captcha API, передавая task_id и API-ключ, пока не будет получен окончательный результат. Если статус остаётся «processing», скрипт выводит сообщение и ждёт заданный интервал времени. При превышении лимита попыток возвращается сообщение об ошибке.

Основной рабочий процесс (функция main)

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

2. Настройка параметров прокси: Если прокси-задания присутствуют, активируется режим с использованием прокси и формируется словарь proxy_details. В противном случае используется режим без прокси.

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 с решением.

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

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

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

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

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

Заключение

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

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