
Привет! Если вы читаете эти строки, значит, ваш парсер или бот в очередной раз уперся в стену под названием «Я не робот». Я прекрасно помню свои первые попытки автоматизации: ты часами вылизываешь логику сбора данных, настраиваешь обход блокировок по IP, запускаешь скрипт… и через десять минут он «падает», потому что сайт выкинул картинку с гидрантами или заставил вводить кривые буквы.
Ощущение, прямо скажем, не из приятных. В этой статье я хочу раз и навсегда закрыть для вас вопрос решения капчи на Python. Мы не будем изобретать велосипед и пытаться обучить нейронку на коленке — мы внедрим профессиональный подход, используя мощь Playwright и проверенные API-сервисы. Погнали!
Оглавление
Почему бесплатные методы обхода капчи больше не работают?
Многие новички в начале пути совершают одну и ту же ошибку — пытаются использовать Tesseract или другие бесплатные OCR-библиотеки для распознавания текста. Давайте будем честны: в 2025 году это работает разве что на сайтах из прошлого десятилетия. Современная капча — это сложная система. Тот же Google анализирует не только то, что вы ввели, но и то, как вы двигали мышкой, какие у вас установлены шрифты и не «палится» ли ваш браузер флагами автоматизации.
Именно поэтому эффективное решение капчи на Python сегодня строится на «разделении труда». Playwright берет на себя роль идеального имитатора человеческого поведения в браузере, а специализированные API-сервисы (вроде RuCaptcha или 2Captcha) выступают в роли «мозга», который за копейки разгадывает саму загадку. Наша задача как программистов — правильно выстроить мост между ними.
📚 Документация: Playwright Python «Playwright позволяет автоматизировать Chromium, Firefox и WebKit с помощью единого API. Он создан для того, чтобы быть быстрым, надежным и поддерживать современные веб-технологии, включая работу в асинхронном режиме».
Пример №1: Решение обычной графической капчи (Image Captcha)
Начнем с классики — картинка с искаженным текстом. Несмотря на засилие сложных систем, этот вид капчи до сих пор встречается на госуслугах, порталах налоговой и многих досках объявлений. Для тренировки используем реальный демо-стенд: https://2captcha.com/demo/normal. Здесь мы можем безопасно отладить наш скрипт.
Код для работы с изображением:
import asyncio
import base64
from playwright.async_api import async_playwright
async def solve_image_captcha():
async with async_playwright() as p:
# Запускаем браузер. headless=False поможет вам видеть, что делает бот
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://2captcha.com/demo/normal")
# 1. Находим элемент картинки капчи по селектору
captcha_locator = page.locator(".demo-captcha__img img")
# Ждем появления картинки, чтобы не сделать скриншот пустого места
await captcha_locator.wait_for(state="visible")
# 2. Делаем "прицельный" скриншот именно этого элемента
image_buffer = await captcha_locator.screenshot()
# Кодируем байты изображения в строку Base64 для передачи через API
base64_image = base64.b64encode(image_buffer).decode('utf-8')
# В реальном сценарии здесь отправляется запрос к API
# Предположим, сервис вернул нам текст "abcd12"
captcha_text = "abcd12"
# 3. Вводим ответ в поле и нажимаем Check
await page.fill("input[name='captcha-side']", captcha_text)
await page.click("button.demo-captcha__send")
print(f"Капча решена: {captcha_text}")
await asyncio.sleep(5)
await browser.close()
asyncio.run(solve_image_captcha())
Объяснение кода:
captcha_locator.screenshot(): Это одна из лучших функций Playwright. Вам не нужно возиться с координатами или обрезать скриншот всей страницы. Мы просто говорим: «сфотографируй этот элемент», и получаем готовый буфер с картинкой.base64.b64encode(image_buffer): Бинарные данные картинки (байты) нельзя просто так запихнуть в JSON. Мы переводим их в текстовый стандарт Base64 — именно его ждут API-сервисы в своих запросах.page.fill(): Мы находим поле ввода через CSS-селектор и имитируем набор текста. Это выглядит для сайта естественнее, чем просто подмена значенияvalueчерез JavaScript.
Пример №2: Обход reCAPTCHA v2 и поиск SiteKey
Теперь перейдем к reCAPTCHA v2 (та самая с витринами и гидрантами). Здесь скриншоты не помогут. Нам нужно получить токен решения, используя секретный идентификатор сайта — SiteKey. Тренируемся на официальном демо: https://www.google.com/recaptcha/api2/demo.
Как найти SiteKey (Инструкция)
SiteKey — это уникальный ID, который Google выдает владельцу сайта. Без него сервис решения не поймет, к какой именно капче подбирать ответ.
- Откройте нужную страницу в браузере.
- Нажмите F12 (Инструменты разработчика) и перейдите на вкладку Elements.
- Нажмите Ctrl + F и введите в поиске
data-sitekey. - Вы увидите строку длиной около 40 символов, например:
6Le-wvkSAAAAAPBqCwY-qS_S_MdxEPC9KLS9j_69. Это и есть наш ключ.
Код решения reCAPTCHA v2:
async def solve_google_recaptcha():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://www.google.com/recaptcha/api2/demo")
# 1. Забираем SiteKey программно прямо со страницы
site_key = await page.get_attribute(".g-recaptcha", "data-sitekey")
print(f"Обнаружен SiteKey: {site_key}")
# 2. Имитируем получение токена от сервиса
# В реальности здесь будет ожидание ответа от RuCaptcha (обычно 30-60 сек)
solved_token = "03AFcWeA7...очень_длинный_код"
# 3. Внедряем токен в скрытое поле 'g-recaptcha-response'
# Поле имеет стиль display: none, поэтому .fill() не сработает
await page.evaluate(f'document.getElementById("g-recaptcha-response").innerHTML="{solved_token}";')
# 4. Вызываем Callback-функцию (ОБЯЗАТЕЛЬНО)
# На демо-странице Google функция называется onSuccess
await page.evaluate("onSuccess();")
# 5. Сабмитим форму
await page.click("#recaptcha-demo-submit")
print("reCAPTCHA успешно пройдена!")
await asyncio.sleep(5)
await browser.close()
Объяснение кода:
page.get_attribute(): Этот метод позволяет динамически вытащить SiteKey. Это профессиональный подход: если владелец сайта изменит ключ, ваш скрипт сам подхватит новый без правки кода.page.evaluate(): Так как поле для токена скрыто от глаз пользователя, обычные методы ввода Playwright его «не видят». Мы используем JavaScript, чтобы напрямую изменить содержимое DOM-дерева.onSuccess(): Запомните этот нюанс. Многие сайты не просто проверяют наличие токена, а ждут сигнала от скриптов Google, что проверка пройдена. Вызов Callback-функции — это тот самый сигнал.
Маскировка: Использование Playwright Stealth
Даже если вы идеально решили капчу, сайт может вас забанить просто за то, что вы — бот. В Playwright «из коробки» есть куча признаков, которые кричат антифрод-системам о том, что браузером управляет скрипт. Чтобы это исправить, нам нужен плагин stealth.
from playwright_stealth import stealth_async
async def run_stealth_mode():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
# Применяем магию Stealth перед переходом на сайт
await stealth_async(page)
await page.goto("https://bot.sannysoft.com/")
# Все проверки на "робота" будут пройдены успешно
Объяснение кода:
stealth_async(page): Эта библиотека подменяет параметрыnavigator.webdriver, имитирует специфические шрифты, параметры WebGL и Canvas. С ней ваш бот выглядит как обычный компьютер соседа, а не как бездушный скрипт на сервере.
📚 Документация: Playwright-Stealth Python «Библиотека предоставляет набор уклонений (evasions), которые позволяют обойти детекторы автоматизации, такие как FingerprintJS и другие».
Обработка ошибок и повторные попытки (Retries)
В реальном мире решение капчи на Python никогда не идет идеально. Сервис API может быть перегружен, работники могут ошибиться, или ваш интернет может моргнуть. Чтобы скрипт не «падал» при первом же чихе, обязательно внедряйте логику повторных попыток.
Пример кода с логикой Retries:
async def solve_with_retries(page, max_retries=3):
attempt = 1
while attempt <= max_retries:
try:
print(f"Попытка решения #{attempt}...")
# 1. Логика получения и решения капчи
# (Тут должен быть ваш код из примеров выше)
# Если дошли до этой строки без ошибок — выходим из цикла
print("Успех!")
return True
except Exception as e:
print(f"Ошибка на попытке {attempt}: {e}")
attempt += 1
# Пауза перед следующей попыткой, чтобы не спамить
await asyncio.sleep(3)
print("Не удалось решить капчу после всех попыток.")
return False
Объяснение кода:
while attempt <= max_retries: Мы создаем цикл с четким ограничением. Это защита от бесконечных трат денег на API, если сайт вдруг радикально обновил защиту.try...except: Это база стабильности. Мы ловим любые ошибки (таймауты, ошибки API, отсутствие элементов) и вместо того, чтобы завершить работу всего скрипта, просто переходим к следующей итерации.asyncio.sleep(3): Важный момент. Нужно дать сайту или API-сервису небольшую передышку перед повторным запросом.
Заключение
Решение капчи на Python — это не магия, а грамотное сочетание инструментов. Playwright дает нам контроль над браузером, API-сервисы решают головоломки, а Stealth-режим и логика Retries делают нашего бота по-настоящему живучим. Надеюсь, этот подробный гайд спасет не один ваш проект от блокировок. Помните: автоматизация должна работать на вас, а не забирать все ваше свободное время на борьбу с капчами.
• Python pathlib: примеры работы — узнайте, как грамотно организовывать хранение скриншотов капчи и логов
• Как писать чистый код на Python — советы по архитектуре ваших скриптов автоматизации
• 10 ошибок новичков в Python — проверьте, не выдает ли ваш бот себя простыми промахами
📢 Подписывайтесь на Telegram-канал PythonAuto, чтобы не пропустить новые гайды по автоматизации, парсингу и разные трюки на Python.
👉 Ваш интерес — лучшая мотивация для новых статей!