GoのHTTPプロキシ経由でCAPTCHAトークンを送信する

著者:solvethree読了時間:1分

対象のウェブサイトには別の Go HTTP クライアントを使用し、solvethree.SuccessfulProxy が選択したプロキシを設定します。返されたブラウザー識別情報で Solution.Token を送信してください。この送信先用のトランスポートは、SDK クライアントの solvethree API 用トランスポートとは分離してください。

このページの内容

タスクを準備する

  1. 1.

    Go SDK と認証情報を設定する

    Go 1.22 以降と、公式の solvethree.com/sdk モジュールのバージョン v0.1.0 を使用します。設定の詳細は Go 連携リファレンスを参照してください。SOLVETHREE_API_KEY にワークスペースの API キーを設定し、サーバー上で保持してください。SOLVETHREE_PROXY には HTTP または HTTPS プロキシの URL を設定します。

  2. 2.

    解決を開始する前にサイトを設定する

    ワークスペースには、対象ホスト名の有効なプロファイルが必要です。まずサイトプロファイルを設定してください。ホスト名とアクションを送信してもプロファイルは作成されません。

  3. 3.

    例の送信先を置き換える

    accounts.example.com、login アクション、アプリケーションのエンドポイントを、連携先に合わせて変更します。Site は完全な URL ではなくホスト名です。reCAPTCHA では Proxy または ProxyCandidates のいずれか一方だけを指定し、タスクの Type と URL フィールドは設定しないでください。デフォルトの reCAPTCHA タイプは Enterprise v3 です。

タスクを解決したプロキシ経由で送信する

Go · 成功したプロキシ経由で送信
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "net/http"
    "net/url"
    "strings"
    "time"
    solvethree "solvethree.com/sdk"
)

func main() {
    client, err := solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"), nil)
    if err != nil { log.Fatal(err) }
    ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
    defer cancel()
    input := solvethree.TaskRequest{Site: "accounts.example.com", Action: "login", Proxy: os.Getenv("SOLVETHREE_PROXY")}
    result, err := client.Solve(ctx, input, solvethree.SolveOptions{})
    if err != nil { log.Fatal(err) }
    fmt.Println("Ready task:", result.ID)

    proxy, ok := solvethree.SuccessfulProxy(input, result)
    if !ok { log.Fatal("No valid successful proxy") }
    proxyURL, err := url.Parse(proxy)
    if err != nil { log.Fatal(err) }
    transport := http.DefaultTransport.(*http.Transport).Clone()
    transport.Proxy = http.ProxyURL(proxyURL)
    defer transport.CloseIdleConnections()
    targetClient := &http.Client{Transport: transport, Timeout: 30*time.Second,
        CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}
    request, err := http.NewRequestWithContext(ctx, "POST", "https://accounts.example.com/login",
        strings.NewReader(url.Values{"g-recaptcha-response": {result.Solution.Token}}.Encode()))
    if err != nil { log.Fatal(err) }

    request.Header.Set("User-Agent", result.Solution.UserAgent)
    request.Header.Set("sec-ch-ua", result.Solution.SecChUA)
    request.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    response, err := targetClient.Do(request)
    if err != nil { log.Fatal(err) }
    defer response.Body.Close()
    fmt.Println("Application HTTP status:", response.StatusCode)
    // Inspect the application response to determine whether submission succeeded.

}

SDK はタスクを解決しますが、ウェブサイトには何も送信しません。解決後、この例では http.DefaultTransport を複製し、http.ProxyURL を使って複製側の Proxy を設定します。そのトランスポートを使うのは別途用意した targetClient だけで、SDK クライアントの API 用トランスポートは変更されません。

プロキシの認証情報は URL のユーザー情報部分に保持してください。url.Parse はプロキシ用トランスポートで使えるように、その情報を保持します。URL を手動で分割したり、プロキシの認証情報を送信先への Authorization ヘッダーとして送ったりせず、ユーザー名やパスワードに含まれる予約文字をパーセントエンコードしてください。

現在プロキシを1つしか指定していない場合でも、元のタスク入力を保持し、SuccessfulProxy を使用してください。ProxyCandidates を使用する場合、成功した候補は、元のリストの1始まりのインデックスである Solution.EgressAttempts によって特定されます。このヘルパーを使えば、どの候補が成功したかを推測せずに済みます。false が返された場合は停止してください。候補リストには、パス、クエリ、フラグメントを含まない、重複のない HTTP または HTTPS プロキシ URL を最大12個指定できます。

送信先のヘッダー、フォームフィールド、セッションを含める

この例では url.Values を使い、Solution.Token を g-recaptcha-response というフィールド名でフォームエンコードし、対応するコンテンツタイプを設定します。アプリケーションが別のフィールド名を想定している場合は置き換えてください。ログイン情報やセッションに紐づく CSRF 対策の値など、エンドポイントで必要な他のフィールドも追加します。CAPTCHA トークンだけでは、完全なログインリクエストにはなりません。

例と同様に、返された UserAgent と SecChUA を使用してください。ソリューションの Headers にも項目が含まれている場合は、それらのヘッダーも送信先へのリクエストに適用してください。この例では、そのコレクションはコピーしていません。ブラウザー識別情報の一貫性を保ち、送信する本文に合ったコンテンツタイプを設定してください。

この例には Cookie jar がありません。送信先でセッションが必要な場合は、net/http/cookiejar で jar を作成し、送信先での処理を開始する前に targetClient.Jar に設定して、ページのリクエストとフォーム送信でそのクライアントを再利用してください。そのセッション全体で、同じ成功したプロキシを使用します。solvethree API クライアントは、送信先のセッション用クライアントではありません。

ソリューションにアクセスする前に、解決処理のエラーを確認してください。利用可能なソリューションがあるのは準備完了のタスクだけです。失敗したタスクでは、errorCode と error が失敗の理由を示します。対象へのリクエストでは、Do のエラーを処理してから、HTTP ステータスを確認し、その後でレスポンスボディを解釈してください。Do がエラーなしでレスポンスを返した場合は、成功以外の HTTP レスポンスも含め、必ず response.Body を閉じてください。

この例では自動リダイレクトを無効にし、アプリケーションのステータスを出力します。レスポンスボディと想定されるリダイレクトを確認して、アプリケーションが送信を受け付けたかどうかを判断してください。タスクが準備完了であることや、HTTP ステータスが成功であることだけでは、受け付けられたとは判断できません。

最初のタスクを実行しましょう。

$5のワークスペースクレジットで始められます。

ワークスペースを作成
GoのHTTPプロキシ経由でCAPTCHAトークンを送信する · solvethree