PowerShellからCAPTCHA APIを呼び出す

著者:solvethree読了時間:1分

PowerShell 7.5+とInvoke-RestMethodを使ってsolvethreeを直接呼び出します。以下のスクリプトはreCAPTCHA Enterpriseタスクを1つ作成し、完了するか、ローカルの待機時間枠を使い切るまで、同じタスクIDをポーリングします。

このページの内容

認証情報と対象の入力値を設定する

  1. 1.

    ワークスペースでサイトを利用可能にする

    コンソールで、対象のホスト名の有効なプロファイルを設定してください。ホスト名とアクションを送信しても、プロファイルは作成されません。まだ設定していない場合は、サイトプロファイルの設定を参照してください。

  2. 2.

    環境変数を指定する

    通常のシークレット管理方法で、PowerShellプロセスの環境に SOLVETHREE_API_KEY と SOLVETHREE_PROXY を設定してください。実行前に両方に値があることを確認してください。APIキーはBearerヘッダーで送信されるもので、タスクのJSONには含めません。

  3. 3.

    例のホスト名とアクションを置き換える

    accounts.example.com と login を、連携に必要なホスト名とアクションに変更してください。完全なURLではなく、ホスト名を使用します。リクエストはデフォルトでEnterprise v3を使用するため、type フィールドも url フィールドも不要です。

1回だけ作成し、タスクIDをポーリングする

PowerShell · 一度だけ作成して復旧用IDを保持
#requires -Version 7.5
$ErrorActionPreference = 'Stop'
$apiBase = 'https://api.solvethree.com/v1'
$headers = @{ Authorization = "Bearer $env:SOLVETHREE_API_KEY"; Accept = 'application/json' }
$taskInput = @{ site = 'accounts.example.com'; action = 'login'; proxy = $env:SOLVETHREE_PROXY; requestId = [guid]::NewGuid().ToString() }
$requestClock = [Diagnostics.Stopwatch]::StartNew()
function Call-TaskApi($Method, $Path, $Payload = $null) {
    $remaining = 180 - $requestClock.Elapsed.TotalSeconds
    if ($remaining -le 0) { throw 'Local deadline reached' }
    $seconds = [int][Math]::Ceiling([Math]::Min(25, $remaining))
    $options = @{ Method = $Method; Uri = "$apiBase$Path"; Headers = $headers;
        ConnectionTimeoutSeconds = $seconds; OperationTimeoutSeconds = $seconds;
        MaximumRetryCount = 0; MaximumRedirection = 0 }
    if ($null -ne $Payload) { $options.Body = $Payload | ConvertTo-Json -Depth 6; $options.ContentType = 'application/json' }
    Invoke-RestMethod @options
}
$taskId = $null
try {
    $result = Call-TaskApi 'POST' '/tasks?waitMs=0' $taskInput
    $taskId = $result.id
    while ($result.status -in @('pending', 'solving')) {
        $escapedId = [uri]::EscapeDataString($taskId)
        $result = Call-TaskApi 'GET' "/tasks/$escapedId`?waitMs=15000"
        if ($result.status -in @('pending', 'solving')) { Start-Sleep -Seconds 1 }
    }
    if ($result.status -ne 'ready') { throw "Task failed: $($result.errorCode)" }
    Write-Host "Ready task: $taskId"
    # Submit $result.solution.token with userAgent/secChUa and the original proxy.
} catch {
    Write-Host "Recovery requestId=$($taskInput.requestId) taskId=$taskId"
    throw
}

スクリプトは /v1/tasks?waitMs=0 にPOSTを1回送信します。その後は、返されたIDに対して waitMs=15000 を指定したGETリクエストを送信します。pending と solving の間はループを継続し、それ以外のステータスになると終了します。

ConvertTo-Json でタスクのハッシュテーブルをシリアライズし、引用符を手動で記述したJSONやシェルコマンドには依存しません。タスクIDはポーリング前にURLエスケープされます。例を調整する際も、これらの処理は維持してください。

Stopwatchは、各API呼び出しの前に180秒のローカル制限時間を確認します。各呼び出しの接続タイムアウトと操作タイムアウトは最大25秒で、残り時間が少なくなると短縮されます。ポーリングで終了状態に達しなかった場合、スクリプトは1秒待機します。この制限時間は無限のポーリングを防ぐためのもので、実経過時間による厳密な打ち切りではありません。

MaximumRetryCount = 0 は自動HTTPリトライを無効にし、MaximumRedirection = 0 はリダイレクトを拒否します。ここで使用するタイムアウトパラメーターにはPowerShell 7.5+が必要で、すべてのPowerShell 7環境で使えるわけではありません。これらのパラメーターは、MicrosoftのInvoke-RestMethodリファレンスに記載されています。

タスクIDではなくトークンを使用する

ready の場合、送信するreCAPTCHAの値は $result.solution.token です。$taskId はsolvethreeのタスクを識別するだけの値です。この例は、対象にアプリケーションのリクエストを送信する前に終了します。

元のプロキシを使用し、返されたソリューションの userAgent と secChUa とともにトークンを送信してください。無関係なブラウザー識別情報に置き換えたり、別の対象に送信したりしないでください。ready はsolvethreeがソリューションを生成したことを意味し、対象がアプリケーションのリクエストを受け入れたことを示すものではありません。

Invoke-RestMethodがHTTP例外または接続例外をスローする

スクリプトが成功レスポンスを処理する前に、APIリクエストが失敗しました。catchブロックは復旧用のIDを出力し、元の例外を再スローします。

試してみましょう: 取得できる場合は、HTTPステータスとレスポンスの詳細を確認してください。無効な入力はそのまま再試行せず、修正してください。タスク作成の結果が不明な場合は、以下の方法で復旧してください。

タスクがfailedを返す

$result.errorCode と $result.error の両方を確認してください。スクリプトがタスクの終了時にスローする例外には、エラーコードのみが含まれます。

試してみましょう: そのタスクのポーリングを停止し、報告された原因に対処してください。たとえば、site-unreachable はタスクのエラーであり、APIリクエスト自体が失敗した証拠ではありません。CAPTCHA APIのエラーを参照してください。

別のタスクを作成せずに、結果が不明なリクエストを復旧する

タイムアウトしても、作成リクエストが失敗したとは限りません。catchブロックは requestId と、受信済みであれば taskId を出力します。これらの値を保存してください。

  1. 1.

    タスクIDがある場合は、そのタスクを取得する

    別のタスクを作成せず、GET /v1/tasks/:id で処理を続けてください。スクリプトのローカル制限時間に達しても、リモートのタスクが失敗したとは限りません。

  2. 2.

    作成時にタスクIDが返されなかった場合は、元のリクエストを再利用する

    同じタスク入力を同じ requestId で再送信し、既存のタスクを復旧してください。そのIDを再利用しながら入力を変更すると、競合が発生します。

  3. 3.

    復旧のためにこのスクリプトを再起動しない

    新たに実行すると新しいGUIDが生成されるため、論理的に新しいリクエストになります。無人実行では、POSTの前に元のrequestIdとタスク入力を安全に保存し、タスクIDが届いたらそれも保存してください。この例は失敗時に復旧用のIDを出力しますが、プロセスが失われた場合に備えて永続化はしません。

プロキシURLに認証情報が含まれる場合は、保存した入力を通常のログに記録しないでください。復旧に必要なのは元の入力であり、APIキーの追加コピーではありません。

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

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

ワークスペースを作成
PowerShellからCAPTCHA APIを呼び出す · solvethree