По роду деятельности я не разработчик, но вращаюсь в этих кругах, так скажем – околоPYTHONная тусовка. Есть знакомые разработчики и даже больше – коллеги.
Как это часто бывает, понадобилось мне организовать решение капчи на Python для одного важного проекта – парсер под Амазон. Было перепробована куча вариантов, израсходована не одна тонна промтов для чата GPT, но никак не поддавалась эта долбанная Амазон капча. В итоге – коллективным разумом (ну как коллективным, просьба была моя, а решение коллеги) был составлен скрипт для обхода капчи на Python, и решение выложить его в общий доступ продиктовано исключительно благими намерениями корыстными побуждениями. Нужны советы, по оптимизации работы этого скрипта, потому что мы с чатом уже все, сдулись. Перепробовали несколько подходов, сломали кучу библиотек, но стабильной работы скрипта в итоге не получили.
Давайте по порядку:
Общее описание скрипта для обхода капчи на Python
Скрипт обхода капчи на Python работает по такому принципу:
Импортирует необходимые для работы библиотеки
Подстановка прокси
Открывает страницу регистрации на Амазон
Решение первой капчи (если ее нет – пропуск)
Заполнение формы регистрации
Решение второй капчи координатным методом
Проверка решения капчи
Закрытие браузера
Теперь разберемся с каждым пунктом отдельно.
Необходимые для решения капчи Python библиотеки
Скрипт использует несколько библиотек:
os
,base64
,BytesIO
- стандартные библиотеки Python, которые используются для работы с файловой системой, кодирования изображений в base64 и работы с потоками байтов (можно сказать, что этот набор библиотек используется для обхода капчи в виде изображения).seleniumbase.Driver
,selenium.webdriver.common.by.By
,selenium.webdriver.common.action_chains.ActionChains
- Эти библиотеки позволяют управлять браузером через Selenium, выполнять поиск элементов на веб-странице и выполнять сложные действия с ними (например, клик по координатам) (таким образом, этот набор библиотек большей степенью предназначен для решения капчи координатным методом, но не стоит забывать, что в принципе все взаимодействие с капчей зависит в данном скрипте от Селениума, так что это самый важный набор библиотек).TwoCaptcha
: Библиотека для работы с сервисом 2Captcha для автоматического распознавания капчи (естественно, решение капчи Python реализовано через сторонний сервис, в нашем случае сервис 2капча).
Подстановка прокси для функционирования скрипта
Изначально скрипт был настроен таким образом, чтобы прокси брались из файла, но так как я достаточно ленивый (Что? Создать файл для прокси, разобраться в каком формате записывать туда прокси, подготовить эти прокси в нужном формате, да вы издеваетесь?), пришлось добавить возможность использования прокси прямо из кода.
То есть, скрипт сперва проверяет, есть ли файл с прокси и если его нет – подгружает прокси из кода. А если и там нет прокси, то скрипт просто забивает на работу и отключается (прям как некоторые работники – «я человек простой, не поставили задачу – просто листаю видосики»)
В принципе обход капчи без прокси в современном мире уже признак дурного тона (особенно если поток огромный), и неважно на Python ты это делаешь или на другом языке.
Открытие страницы регистрации на Амазон
Далее скрипт открывает страницу регистрации на Амазон (за это отвечает эта функция - driver.uc_open_with_reconnect
:). Конечная цель ведь у скрипта – регистрация на сайте, а не распознавание капчи (хотя больше он пока что ничего сделать и не может, если быть до конца честным.
Решение первой капчи на Python
Вот мы наконец-то и добрались до ключевой функции (вернее ее части) - обход капчи либо пропуск, если капчи нет. Речь про простую текстовую Амазон капчу, она то появляется то нет (все зависит от того, какие дни у Амазон).
Работает это так – скрипт при помощи selenium находит изображение капчи на странице и делает его скриншот, после чего преобразует скрин в формат base64
и отправляет получившийся набор букв и символов на сервис 2капча для обхода, а после получения ответа от сервера подставляет текст в специальное поле и жмет кнопку «Продолжить».
Соответсвенно, если обходить нечего (капча не появилась) этот пункт просто пропускается и скрипт переходит к следующему.
Заполнение формы регистрации
Как вы помните, перед тем, как попытаться решить капчу скрипт открыл страницу регистрации, собственно к ней он и возвращается и заполняет регистрационную форму.
Данные для регистрационной формы загружаются прямиком из кода, и это сделано как раз по той причине, что необходимо до конца допилить модуль распознавания капчи.
В идеале, сюда можно дописать свое решение, которое будет брать данные для заполнения формы из файла методом перебора и таким образом в автоматическом режиме можно заполнять много форм.
Обход капчи Python координатным методом
С первой капчей, за все время тестирования этого модуля у меня ни разу не возникло никаких заморочек (ну тупо Амазон был в хорошем расположении духа и ни разу не выдал мне текстовую капчу), а вот со второй появились вопросики, как к скрипту, так и к комьюнити.
Давайте разберемся:
Итак, вторая капча более сложная и требует указания куда нужно кликнуть, чтобы ее обойти. Принцип работы скрипта такой – делается скриншот и отправляется на сервис для получения координат.
Сервис присылает координаты и скрипт, используя ActionChains
перемещает курсор на указанные координаты, после чего переключается во фрейм и нажимает кнопку подтверждения.
И вот дальше происходит то самое волшебство тот самый затык. Либо в момент распознавания, либо на шаге проверки иногда происходит провис, то есть капча либо не решается, либо заканчивается время на решение капчи и она обновляется, не успев получить правильный результат. В большинстве случаев все решается, но вот это исключение из большинства случаев мне и не дает покоя…
Ниже приведу сам скрипт, может кому то будет полезным, а может кто-то в комментах даст рекомендацию, что по его мнению можно доработать, чтобы пофиксить этот момент?
Либо, это не исправить, так как ответ такой – «Это же Амазон»…
import os
import base64
from io import BytesIO
from seleniumbase import Driver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from twocaptcha import TwoCaptcha # pip3 install 2captcha-python
# Прокси для ручного ввода
manual_proxy = "http://login:password@ip:port" # Замените на ваш прокси
# Функция для чтения прокси из файла
def get_proxy_from_file(file_path):
if os.path.exists(file_path):
with open(file_path, 'r') as file:
proxy = file.read().strip()
return proxy
return None
# Попробуем сначала подключить прокси из внешнего файла, если файл отсутствует, используем ручное значение
proxy_file_path = "proxy.txt" # Имя файла с прокси
proxy = get_proxy_from_file(proxy_file_path) or manual_proxy
my_key = "API Key 2captcha"
solver = TwoCaptcha(my_key, defaultTimeout=70)
agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
# Инициализация драйвера с прокси
driver = Driver(uc=True, headless=False, proxy=proxy, agent=agent) # headless=True for invisible mode
try:
url = "https://www.amazon.com/ap/register?openid.pape.max_auth_age=0&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&pageId=usflex&ignoreAuthState=1&openid.assoc_handle=usflex&openid.mode=checkid_setup&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&prepopulatedLoginId=&failedSignInCount=0&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&disableLoginPrepopulate=1&switch_account=signin&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0"
driver.uc_open_with_reconnect(url, 5)
# Решение первой капчи
try:
my_img = driver.find_element("body > div > div.a-row.a-spacing-double-large > div.a-section > div > div > form > div.a-row.a-spacing-large > div > div > div.a-row.a-text-center > img")
print("SOLVE FIRST CAPTCHA...")
screenshot = my_img.screenshot_as_png
screenshot_bytes = BytesIO(screenshot)
base64_screenshot = base64.b64encode(screenshot_bytes.getvalue()).decode('utf-8')
result = solver.normal(base64_screenshot)
print('result: ' + str(result)) # Отправка запроса на сервис 2Captcha
res = result['code']
driver.find_element(By.ID, "captchacharacters").send_keys(f"{res}")
driver.find_element(By.CLASS_NAME, "a-button-inner").click()
except:
pass
# Ожидание и заполнение формы
driver.sleep(1)
print("Fill out the form")
driver.find_element(By.ID, "ap_customer_name").send_keys("Alex0053") # Заполнение формы
driver.find_element(By.ID, "ap_email").send_keys("some_post43120@gmail.com")
driver.find_element(By.ID, "ap_password").send_keys("password40000A#")
driver.find_element(By.ID, "ap_password_check").send_keys("password40000A#")
driver.find_element(By.ID, "continue").click()
driver.sleep(10)
# Вторая капча - координатная
while True:
try:
cap_img = driver.find_element(By.ID, "cvf-aamation-challenge-iframe") # Доработка элемента фрейма
print("SOLVE SECOND-COORD CAPTCHA...")
screenshot = cap_img.screenshot_as_png
screenshot_bytes = BytesIO(screenshot)
base64_screenshot = base64.b64encode(screenshot_bytes.getvalue()).decode('utf-8')
element_position = cap_img.location
result = solver.coordinates(base64_screenshot, lang='en', min_clicks=1, max_clicks=1)
x = str(result['code']).split(":")[1].split(",")[0].replace("x=", "")
y = str(result['code']).split(":")[1].split(",")[1].replace("y=", "")
print('result: ' + str(result))
x_coord = element_position["x"] + int(x)
y_coord = element_position["y"] + int(y)
actions = ActionChains(driver)
actions.move_by_offset(x_coord, y_coord).click().perform()
driver.sleep(2)
actions.reset_actions()
driver.switch_to_frame(cap_img)
driver.find_element(By.ID, "amzn-btn-verify-internal").click()
driver.switch_to.default_content()
driver.sleep(7)
except Exception as e:
print(e)
try:
driver.find_element('form[id="verification-code-form"]')
print("CAPTCHA PASSED!!!")
break
except:
pass
driver.sleep(3)
# Последний блок кода, если нужно
except Exception as e:
print(e)
finally:
driver.close()
driver.quit()
Обход капчи Python – раздел которого в коде нет
У Амазон еще есть третий вид капчи, Фанкапча, и я не смог победить ее в данном контексте, поэтому просто выпилил из этого кода на всякий случай. Да и Фанкапча за все время тестирования мне так ни разу не встретилась (но из разговоров мудрейших я знаю что она там есть, где то в чертогах Амазона). Ходят легенды, что есть специально обученный мужик, назовем его просто СОМ, который руками меняет условия для обхода капчи, либо дизайн страницы.
Никто этого СОМа никогда не видел, но у вечерами, когда ITшники собираются у костра этой байкой пугают джунов.
В общем – скрипт Фанкапчу не решает, но готов к конструктиву и предложениям, как сделать так, чтобы начал решать.
Итого вывод: Скрипт работает, обход капчи осуществляется, но встречаются провисы – было бы неплохо, если бы на них указали (желательно без минусения)
Скрипт не решает Фанкапчу, но на первый взгляд и не нужОна нам эта ваш фанкапча, но если нужна – также, буду рад почитать мнение коммьюнити.
uralhi
А качпча на Амазон вылазит при каждом запросе или ситуативно при превышении частоты запросов? И сам парсинг выполняется как часто?
В кейсе когда нужно несколько раз в год скачать большой массив данных защищённых капчей я пришел к решению что тратить ресурсы на обход капчи смысла нет - проще сделать подуавтоматизированное решение при котором RPA качает данные, а в случае возникновения капчи тормозит процесс, сигнализирует пользователю и ждёт от него прохождения капчи....
Ну и поскольку срочности в загрузке данных не было, а необходимость периодически посматривать на ход RPA меня не сильно напрягал - это оказалось оптимальным решением.
Markus_automation Автор
У меня капча выползала каждый раз. Я думаю это еще от прокси сильно зависит (от их качества)