Как решать Amazon (AWS WAF) CAPTCHA и Challenge при веб-скрапинге
AWS WAF (сервис от компании Amazon) представляет два основных вида защиты веб-ресурсов от нежелательных автоматических действий:
- CAPTCHA – предлагает пользователю решить такие задачи, как: ввод текста в специальное поле, перемещение слайдера, выделение определённых объектов на изображении или перемещение элементов в заданное место. Также в качестве альтернативы предлагаются аудио-капчи, где необходимо прослушать и распознать слова, звучащие на фоне шума, и ввести их в соответствующее поле.
- Challenge – здесь уже пользователю для взаимодействия с сайтом ничего разгадывать не нужно – проверка происходит в фоновом режиме, анализируя параметры сессии и поведение запросов (например, частота запросов, использование JavaScript, поведение мыши, наличие/отсутствие куки). Если проверка проходит успешно, пользователь продолжает дальше работать с сайтом, а если нет – запрос может быть заблокирован, или пользователю может быть показана CAPTCHA для дополнительной проверки. Если система распознает признаки автоматизации, она может повысить уровень проверки, чтобы обеспечить безопасность и защиту сайта от несанкционированного доступа.
Как решать капчи Amazon с помощью CapMonster Cloud
Система защиты Amazon тщательно разработана и обеспечивает высокий уровень безопасности, она постоянно обновляется и усложняет ботам доступ к сайтам. Тем не менее, в целях тестирования сайтов, безопасного парсинга и отладки её можно решить с помощью облачного сервиса CapMonster Cloud.
Поиск данных капчи
Для решения такого типа капчи нужно перейти на целевой сайт с капчей, открыть Инструменты разработчика и получить необходимые данные капчи – websiteKey, context, iv и challengeScript.
Вот более подробная инструкция:
- Загрузите нужную страницу, откройте Инструменты разработчика, перейдите во вкладку Сеть и найдите строку документа с ответом 405:
2. Выберите этот документ и перейдите во вкладку Response:
3. Найдите объект window.gokuProps, в нём вы найдёте все необходимые параметры:
Таблица с необходимыми параметрами и их значениями:
Также вы можете автоматически получить параметры AWS WAF капчи, используя следующий JavaScript-код:
// Извлечение параметров капчи
var gokuProps = window.gokuProps;
var websiteKey = gokuProps ? gokuProps.key : "Не найдено";
var context = gokuProps ? gokuProps.context : "Не найдено";
var iv = gokuProps ? gokuProps.iv : "Не найдено";
// Извлечение URL скриптов капчи
var scripts = Array.from(document.querySelectorAll('script'));
var challengeScriptUrl = scripts.find(script => script.src.includes('challenge.js'))?.src || "Не найдено";
var captchaScriptUrl = scripts.find(script => script.src.includes('captcha.js'))?.src || "Не найдено";
// Вывод параметров и URL скриптов
console.log("Website Key: " + websiteKey);
console.log("Context: " + context);
console.log("IV: " + iv);
console.log("Challenge Script URL: " + challengeScriptUrl);
console.log("Captcha Script URL: " + captchaScriptUrl);
Создание запроса, отправка задачи на сервер, получение результата
Когда вам известны все параметры капчи, вы можете сформировать задачу для отправки на сервер CapMonster Cloud.
Пример запроса:
Используется метод https://api.capmonster.cloud/createTask
Формат запроса: JSON POST
{
"clientKey": "API_KEY",
"task": {
"type": "AmazonTaskProxyless",
"websiteURL": "https://efw47fpad9.execute-api.us-east-1.amazonaws.com/latest",
"challengeScript": "https://41bcdd4fb3cb.610cd090.us-east-1.token.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/challenge.js",
"captchaScript": "https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js",
"websiteKey": "AQIDA...wZwdADFLWk7XOA==",
"context": "qoJYgnKsc...aormh/dYYK+Y=",
"iv": "CgAAXFFFFSAAABVk",
"cookieSolution": true
}
}
Пример ответа:
{
"errorId":0,
"taskId":407533072
}
Получение результата:
Используйте метод getTaskResult, чтобы получить решение AmazonTask
https://api.capmonster.cloud/getTaskResult
Пример ответа:
{
"errorId":0,
"status":"ready",
"solution": {
"cookies": {
"aws-waf-token": "10115f5b-ebd8-45c7-851e-cfd4f6a82e3e:EAoAua1QezAhAAAA:dp7sp2rXIRcnJcmpWOC1vIu+yq/A3EbR6b6K7c67P49usNF1f1bt/Af5pNcZ7TKZlW+jIZ7QfNs8zjjqiu8C9XQq50Pmv2DxUlyFtfPZkGwk0d27Ocznk18/IOOa49Rydx+/XkGA7xoGLNaUelzNX34PlyXjoOtL0rzYBxMAQy0D1tn+Q5u97kJBjs5Mytqu9tXPIPCTSn4dfXv5llSkv9pxBEnnhwz6HEdmdJMdfur+YRW1MgCX7i3L2Y0/CNL8kd8CEhTMzwyoXekrzBM="
},
"userAgent": "userAgentPlaceholder"
}
}
Пример кода для решения Amazon капчи при веб-скрапинге на Python:
При веб-скрапинге могут возникнуть различные препятствия, например, в виде приостановки скрипта из-за появившейся на целевом сайте капчи от Amazon. Чтобы обойти это препятствие, вы можете добавить в свой скрапер дополнительный код для автоматического решения капчи, который будет дожидаться фрейма капчи, самостоятельно извлекать все нужные параметры и отправлять решение на сервер CapMonster Cloud.
Как это можно реализовать: допустим, имеется скрипт для скрапинга погодного сайта на Python с использованием Selenium:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
try:
# Открытие главной страницы с погодой
driver.get('https://example.com')
# Поиск поля для ввода города, ввод названия города
search_box = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "header-location-search")) # Замените на нужное значение
)
search_box.send_keys("Moscow") # Замените на нужное значение
search_box.send_keys(Keys.RETURN)
# Ожидание загрузки страницы с результатами поиска
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, 'div.locations-list') )# Замените на нужное значение
)
# Поиск и клик на первый результат поиска
first_result = driver.find_element(By.CSS_SELECTOR, 'div.locations-list a') # Замените на нужное значение
first_result.click()
И на этой же странице нужно решить капчу от Amazon. Добавьте код для решения капчи:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os
import requests
import time
# API_KEY для CapMonster Cloud
API_KEY = os.getenv('CAPMONSTER_API_KEY')
CREATE_TASK_URL = 'https://api.capmonster.cloud/createTask'
GET_TASK_RESULT_URL = 'https://api.capmonster.cloud/getTaskResult'
def create_task(website_key, context, iv, challenge_script_url, captcha_script_url):
print("Создание задачи...")
task_data = {
"clientKey": API_KEY,
"task": {
"type": "AmazonTaskProxyless",
"websiteURL": 'https://example.com', # Замените на нужное значение
"challengeScript": challenge_script_url,
"captchaScript": captcha_script_url,
"websiteKey": website_key,
"context": context,
"iv": iv,
"cookieSolution": False # Замените на True, если необходимы куки "aws-waf-token"
}
}
response = requests.post(CREATE_TASK_URL, json=task_data)
response_json = response.json()
if response_json['errorId'] == 0:
print(f"Задача успешно создана. Task ID: {response_json['taskId']}")
return response_json['taskId']
else:
print(f"Ошибка при создании задачи: {response_json['errorCode']}")
return None
def get_task_result(task_id):
print("Получение результата задачи...")
result_data = {"clientKey": API_KEY, "taskId": task_id}
while True:
response = requests.post(GET_TASK_RESULT_URL, json=result_data)
response_json = response.json()
if response_json['status'] == 'ready':
print(f"Результат задачи готов: {response_json}")
return response_json
elif response_json['status'] == 'processing':
print("Задача все еще обрабатывается...")
time.sleep(5)
else:
print(f"Ошибка при получении результата задачи: {response_json['errorCode']}")
return response_json
# Запуск браузера
driver = webdriver.Chrome()
try:
# Открытие главной страницы
print("Открытие страницы...")
driver.get('https://example.com')
# Ввод города для поиска
search_box = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "header-location-search"))
)
search_box.send_keys("Moscow") # Замените на нужный вам город
search_box.send_keys(Keys.RETURN)
# Ожидание появления CAPTCHA
print("Ожидание iframe...")
iframe = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, 'iframe[src*="execute-api"]'))
)
driver.switch_to.frame(iframe)
print("Ожидание CAPTCHA, извлечение параметров...")
WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#captcha-container'))
)
goku_props = driver.execute_script("return window.gokuProps;")
website_key = goku_props["key"]
context = goku_props["context"]
iv = goku_props["iv"]
challenge_script_url, captcha_script_url = [
driver.execute_script(f"return document.querySelector('script[src*=\"{x}\"]').src;")
for x in ("challenge.js", "captcha.js")
]
# Создание и решение CAPTCHA задачи
task_id = create_task(website_key, context, iv, challenge_script_url, captcha_script_url)
if task_id:
result = get_task_result(task_id)
# Используйте result для отправки решения CAPTCHA на страницу, если необходимо
# После решения CAPTCHA продолжайте обработку результатов поиска
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, 'div.locations-list')) # Замените на нужное значение
)
first_result = driver.find_element(By.CSS_SELECTOR, 'div.locations-list a') # Замените на нужное значение
first_result.click()
# Остальные действия
finally:
print("Закрытие браузера...")
driver.quit()
Более подробное объяснение обновлённого кода:
- Дополнительный импорт библиотек requests (позволяет отправлять HTTP-запросы для взаимодействия с API CapMonster Cloud) и time (используется для приостановки выполнения кода на определённое время):
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os
import requests
import time
- Добавление переменных, которые содержат ключ API для аутентификации и URL-адреса для создания задач и получения результатов от CapMonster Cloud:
API_KEY = os.getenv('CAPMONSTER_API_KEY')
CREATE_TASK_URL = 'https://api.capmonster.cloud/createTask'
GET_TASK_RESULT_URL = 'https://api.capmonster.cloud/getTaskResult'
- Добавление функции, которая принимает несколько параметров, необходимых для создания задачи на решение капчи. Она отправляет POST-запрос на сервер CapMonster Cloud с данными о задаче. Если задача успешно создается, функция возвращает taskId:
def create_task(website_key, context, iv, challenge_script_url, captcha_script_url):
# ... код функции
- Добавление функции для отправки POST-запроса для проверки статуса задачи. Если статус задачи 'ready', функция возвращает результат, иначе ждёт и проверяет статус снова:
def get_task_result(task_id):
# ... код функции
- После инициализации браузера и открытия целевой страницы (здесь https://example.com как пример) ожидание появления поля поиска, ввод в него названия города и отправка формы:
search_box = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "header-location-search"))
)
search_box.send_keys("Moscow")
search_box.send_keys(Keys.RETURN)
- Далее ожидание появления iframe с капчей, переключение на него, извлечение параметров, необходимых для решения капчи: website_key, context, iv, а также URL-адресов скриптов:
iframe = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, 'iframe[src*="execute-api"]'))
)
driver.switch_to.frame(iframe)
—-----
goku_props = driver.execute_script("return window.gokuProps;")
website_key = goku_props["key"]
context = goku_props["context"]
iv = goku_props["iv"]
challenge_script_url, captcha_script_url = [
driver.execute_script(f"return document.querySelector('script[src*=\"{x}\"]').src;")
for x in ("challenge.js", "captcha.js")
]
- Создание задачи для решения CAPTCHA и ожидание получения результата:
task_id = create_task(website_key, context, iv, challenge_script_url, captcha_script_url)
if task_id:
result = get_task_result(task_id)
- Продолжение скрапинга:
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, 'div.locations-list'))
)
first_result = driver.find_element(By.CSS_SELECTOR, 'div.locations-list a')
first_result.click()
# Остальные действия ...
Советы и рекомендации
Вышеописанный код приведен в качестве примера и демонстрирует общую логику выполнения действий. Все действия и названия элементов зависят от конкретного сайта и его структуры. Вам потребуется изучить HTML-код сайта, а также ознакомиться с документацией инструментов, которые вы планируете использовать для веб-скрапинга. Каждый сайт уникален, и для успешного скрапинга может потребоваться адаптация кода и подходов в зависимости от особенностей целевого ресурса. Также работа с капчей от Amazon имеет свои нюансы, которые необходимо учитывать.
Вот несколько общих полезных советов для успешного веб-скрапинга и решения Amazon captcha (AWS WAF):
- Асинхронность. В нашем простом примере кода скрапинга и решения капчи асинхронный метод не используется. Однако если вы работаете с большим объёмом данных или сайтами с медленным откликом, то лучше использовать асинхронное программирование для параллельного выполнения задач и ускорения процесса.
- Безголовый режим. Запускайте браузер в безголовом режиме, чтобы ускорить работу и сэкономить ресурсы. Без отображения графического интерфейса браузера процесс может быть более эффективным.
- Графический браузер. Если сайт требует сложного взаимодействия, которое невозможно в безголовом режиме, используйте графический браузер. Это поможет вам справляться с элементами интерфейса, лучше тестировать ваш код, а также избегать некоторых ошибок и блокировок сайтов, которые могут закрыть доступ при обнаружении headless-браузеров.
- Смена IP-адреса и User-Agent. Чтобы избежать блокировок и ограничений со стороны сайта, регулярно меняйте IP-адрес и User-Agent. Используйте качественные прокси-серверы, а также меняйте User-Agent в запросах, чтобы сайт не заподозрил автоматизированное поведение.
- Обработка динамических CAPTCHA. Amazon использует капчи, которые могут меняться в зависимости от времени или активности, а также постоянно обновляет свои методы защиты от ботов. Убедитесь, что ваш скрипт адаптируется к этим изменениям и корректно обрабатывает их. Следите за обновлениями и новостями сервисов для решения капчи.
- Уменьшение частоты запросов. Не делайте запросы слишком часто, чтобы не привлекать внимание анти-ботов Amazon, или распределяйте их между разными IP-адресами.
Полезные ссылки:
Документация Selenium WebDriver
Документация API CapMonster Cloud
Решение капчи от Amazon (AWS WAF) может вызвать значительные затруднения при сборе данных. Однако, зная основные принципы работы этой системы и применяя правильные инструменты, можно эффективно справляться с такими задачами.
Мы рассмотрели ключевые моменты, включая описание этого типа капчи и её решения с помощью CapMonster Cloud. Важнейшими этапами являются точное извлечение необходимых параметров капчи, создание и отправка задачи на сервер, а также получение и использование решения капчи. Мы также рассмотрели пример кода для Python, который показывает в общих чертах, как интегрировать решение капчи в процесс веб-скрапинга. Успех в этой области зависит не только от технических навыков, но и умения быстро адаптироваться к изменениям и нововведениям в методах защиты от ботов.
NB: Напоминаем, что продукт используется для автоматизации тестирования на ваших собственных сайтах и на сайтах, к которым у вас есть доступ на законных основаниях.