Résoudre reCAPTCHA Enterprise avec Ruby
Utilisez Net::HTTP de Ruby pour créer une tâche reCAPTCHA Enterprise et interroger son état jusqu’à ce qu’elle soit prête ou en échec. L’exemple ci-dessous appelle directement l’API REST de solvethree ; il ne nécessite pas de SDK Ruby.
Sur cette page
Configurer le site et l’environnement
- 1.
Activer le profil de site
Configurez le nom d’hôte cible dans la console solvethree et assurez-vous que son profil est actif pour votre espace de travail. L’envoi d’un nom d’hôte et d’une action ne crée pas de profil. Consultez la configuration du profil de site.
- 2.
Définir les variables d’environnement
Définissez
SOLVETHREE_API_KEYsur la clé API de votre espace de travail etSOLVETHREE_PROXYsur l’URL du proxy HTTP ou HTTPS que vous utiliserez aussi pour envoyer le jeton à la cible. Conservez la clé sur le serveur. - 3.
Modifier les paramètres de l’exemple
Remplacez
accounts.example.compar le nom d’hôte cible, et non une URL complète, et remplacezloginpar l’action requise par cette cible. La requête utilise un seulproxy; n’ajoutez pas aussiproxyCandidates. Ometteztypeeturl. L’omission derecaptchaTypesélectionne la valeur par défaut,enterprise-v3.
Enregistrez l’exemple sous solve.rb et exécutez-le avec Ruby après avoir défini ces variables. Il charge net/http, json et securerandom ; JSON gère le corps de la requête et les réponses de l’API.
Créer une seule fois, puis interroger l’identifiant de tâche
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
endLe script envoie une seule requête de création, enregistre l’identifiant de tâche renvoyé et récupère cette tâche tant que son statut est pending ou solving. Seul ready fournit une solution utilisable. Chaque réponse doit avoir un statut HTTP de réussite avant que son corps soit analysé comme une réponse de réussite.
HTTPS est activé explicitement. Les nouvelles tentatives automatiques sont désactivées, et les redirections sont rejetées par la vérification du statut HTTP plutôt que suivies. Le proxy dans le corps de la tâche sert à la résolution ; il ne configure pas la connexion de Ruby à l’API solvethree.
L’échéance monotone partagée accorde à l’interrogation un budget local de 180 secondes. Les délais d’expiration de connexion, de lecture et d’écriture sont plafonnés selon le temps restant au démarrage de chaque requête. Considérez ce budget comme une limite d’interrogation, et non comme un délai strict d’annulation d’une requête en cours. La documentation Ruby Net::HTTP décrit les différents paramètres de délai d’expiration.
Envoyer le jeton avec son identité de navigateur
L’exemple affiche l’identifiant de la tâche prête, pas le jeton. Lisez solution.token dans le résultat prêt et placez-le dans le champ de jeton attendu par la requête cible. N’envoyez pas l’identifiant de tâche à la place.
Utilisez la valeur solution.userAgent renvoyée pour l’en-tête User-Agent et solution.secChUa pour Sec-CH-UA. Envoyez la requête à la cible prévue via le même proxy que celui fourni à cette tâche. Ne remplacez pas l’identité renvoyée par les en-têtes d’un autre navigateur.
Une tâche prête signifie que solvethree a généré une solution. Vérifiez séparément la réponse de la cible pour déterminer si elle a accepté votre requête applicative.
Gérer les échecs sans créer de tâches en double
- Le script lève une erreur HTTP de l’API.
Examinez la réponse HTTP non réussie. Il s’agit d’une erreur au niveau de la requête, pas d’un résultat terminal de tâche.
Essayez ceci : Diagnostiquez cette réponse avant de réessayer. Ne renvoyez pas à répétition des paramètres invalides inchangés.
- La tâche atteint le statut
failed. Examinez à la fois
errorCodeeterrordans le résultat. Le message de l’exception levée par l’exemple ne contient queerrorCode.Essayez ceci : Cessez d’interroger cette tâche et corrigez la cause signalée. Les résolutions échouées sont remboursées ; un échec ne signifie pas nécessairement que le crédit est insuffisant.
- La création expire avant la réception d’un identifiant de tâche.
Conservez le
requestIdde récupération écrit sur la sortie d’erreur standard. Une expiration ne prouve pas que la création a échoué.Essayez ceci : Récupérez la tâche en envoyant une requête de tâche identique avec ce même identifiant de requête. Ne vous contentez pas de relancer le script : une nouvelle exécution génère un nouvel identifiant et peut créer une autre tâche.
- L’interrogation atteint l’échéance locale ou perd sa connexion.
Conservez les identifiants de tâche et de requête consignés dans les journaux.
Essayez ceci : Récupérez la tâche dont vous connaissez l’identifiant avant d’en créer une autre. Une exception locale n’est pas un statut terminal de tâche.
Pour permettre une récupération après un redémarrage du processus, conservez l’identifiant de requête et les paramètres d’origine de la tâche avant d’envoyer le POST, puis conservez l’identifiant de tâche une fois reçu. Réutiliser un identifiant de requête avec des paramètres identiques renvoie la tâche existante ; modifier les paramètres tout en conservant cet identifiant provoque un conflit. Consultez la gestion des erreurs API pour l’étape de diagnostic suivante.
Sources et référence de l’API
Lancez votre première tâche.
Démarrez avec $5 de crédit dans votre espace de travail.