Решайте reCAPTCHA Enterprise с Ruby
Используйте Net::HTTP из Ruby, чтобы создать задачу reCAPTCHA Enterprise и опрашивать её до готовности или ошибки. Пример ниже напрямую вызывает REST API solvethree; Ruby SDK не требуется.
На этой странице
Настройте сайт и окружение
- 1.
Активируйте профиль сайта
Настройте целевое имя хоста в консоли solvethree и убедитесь, что его профиль активен для вашего рабочего пространства. Отправка имени хоста и действия не создаёт профиль. См. настройку профиля сайта.
- 2.
Задайте переменные окружения
Задайте в
SOLVETHREE_API_KEYAPI-ключ рабочего пространства, а вSOLVETHREE_PROXY— URL HTTP- или HTTPS-прокси, который вы также будете использовать при отправке токена на целевой сайт. Храните ключ на сервере. - 3.
Измените входные параметры примера
Замените
accounts.example.comна целевое имя хоста — не полный URL — и заменитеloginна действие, требуемое целевым сайтом. Запрос использует одинproxy; не добавляйте такжеproxyCandidates. Не указывайтеtypeиurl. Если не указыватьrecaptchaType, используется значение по умолчанию —enterprise-v3.
Сохраните пример как solve.rb и запустите его с помощью Ruby после настройки этих переменных. Он загружает net/http, json и securerandom; JSON используется для тела запроса и ответов API.
Создайте задачу один раз, затем опрашивайте её по идентификатору
require 'net/http'
require 'json'
require 'securerandom'
api = 'https://api.solvethree.com/v1'
input = {site: 'accounts.example.com', action: 'login', proxy: ENV.fetch('SOLVETHREE_PROXY'), requestId: SecureRandom.uuid}
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 180
call = lambda do |method, path, body = nil|
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
raise 'Local deadline reached' if remaining <= 0
uri = URI(api + path)
request = method == :post ? Net::HTTP::Post.new(uri) : Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer ' + ENV.fetch('SOLVETHREE_API_KEY')
request['Accept'] = 'application/json'
if body
request['Content-Type'] = 'application/json'
request.body = JSON.generate(body)
end
# Net::HTTP's own proxy configuration is separate from input[:proxy].
http = Net::HTTP.new(uri.hostname, uri.port, nil)
http.use_ssl = uri.scheme == 'https'
http.open_timeout = [10, remaining].min
http.read_timeout = [25, remaining].min
http.write_timeout = [25, remaining].min
http.max_retries = 0
response = http.request(request)
raise "API HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)
end
task_id = nil
begin
result = call.call(:post, '/tasks?waitMs=0', input)
task_id = result.fetch('id')
while %w[pending solving].include?(result.fetch('status'))
result = call.call(:get, '/tasks/' + URI.encode_www_form_component(task_id) + '?waitMs=15000')
sleep(1) if %w[pending solving].include?(result.fetch('status'))
end
raise "Task failed: #{result['errorCode']}" unless result['status'] == 'ready'
puts "Ready task: #{task_id}"
# Submit result['solution']['token'] with its userAgent/secChUa and original proxy.
rescue StandardError => error
warn "Recovery requestId=#{input[:requestId]} taskId=#{task_id || 'unknown'}"
raise error
endСкрипт отправляет один запрос на создание, сохраняет возвращённый идентификатор задачи и получает эту задачу, пока её статус — pending или solving. Только ready предоставляет пригодное для использования решение. Каждый ответ должен иметь успешный HTTP-статус, прежде чем его тело будет разобрано как данные успешного ответа.
HTTPS включён явно. Автоматические повторные попытки отключены, а перенаправления отклоняются проверкой HTTP-статуса, а не выполняются. Прокси в теле задачи предназначен для решения; он не настраивает подключение Ruby к API solvethree.
Общий срок ожидания, отсчитываемый по монотонным часам, задаёт локальный лимит опроса в 180 секунд. Тайм-ауты подключения, чтения и записи ограничиваются временем, оставшимся на момент начала каждого запроса. Считайте этот лимит ограничением опроса, а не жёстким таймером отмены уже выполняющегося запроса. В документации Ruby Net::HTTP описаны отдельные настройки тайм-аутов.
Отправляйте токен с его идентификационными данными браузера
Пример выводит идентификатор готовой задачи, а не токен. Прочитайте solution.token из результата готовой задачи и поместите его в предусмотренное для токена поле запроса к целевому сайту. Не отправляйте вместо него идентификатор задачи.
Используйте возвращённое значение solution.userAgent для заголовка User-Agent, а solution.secChUa — для Sec-CH-UA. Отправляйте запрос на нужный целевой сайт через тот же прокси, который указан в этой задаче. Не заменяйте возвращённые идентификационные данные заголовками постороннего браузера.
Готовая задача означает, что solvethree сгенерировал решение. Отдельно проверьте ответ целевого сайта, чтобы определить, принял ли он запрос вашего приложения.
Обрабатывайте ошибки, не создавая дубликаты задач
- Скрипт выдаёт HTTP-ошибку API.
Изучите неуспешный HTTP-ответ. Это ошибка на уровне запроса, а не конечный результат задачи.
Попробуйте: Выясните причину такого ответа перед повторной попыткой. Не отправляйте многократно одни и те же некорректные параметры.
- Задача переходит в статус
failed. Изучите и
errorCode, иerrorв результате. Сообщение исключения в примере содержит толькоerrorCode.Попробуйте: Прекратите опрос этой задачи и устраните указанную причину. Средства за неудачные решения возвращаются; ошибка не обязательно означает нехватку средств.
- Тайм-аут создания наступает до получения идентификатора задачи.
Сохраните
requestIdдля восстановления, выведенный в стандартный поток ошибок. Тайм-аут не доказывает, что создание завершилось неудачей.Попробуйте: Для восстановления отправьте идентичный запрос задачи с тем же идентификатором запроса. Не запускайте скрипт просто заново: при новом запуске генерируется новый идентификатор и может быть создана ещё одна задача.
- При опросе истекает локальный срок ожидания или теряется соединение.
Сохраните записанные в журнал идентификаторы задачи и запроса.
Попробуйте: Получите задачу по известному идентификатору, прежде чем создавать новую. Локальное исключение не является конечным статусом задачи.
Для восстановления после перезапуска процесса сохраните идентификатор запроса и исходные параметры задачи до отправки POST, а затем сохраните идентификатор задачи, когда он будет возвращён. Повторное использование идентификатора запроса с идентичными параметрами возвращает существующую задачу; изменение параметров с сохранением этого идентификатора вызывает конфликт. Следующий шаг диагностики описан в разделе обработка ошибок API.
Источники и справочник API
Запустите первую задачу.
Начните с $5 на балансе рабочего пространства.