通过 Go HTTP 代理提交 CAPTCHA 令牌
为目标网站使用独立的 Go HTTP 客户端,并配置为使用 solvethree.SuccessfulProxy 选出的代理。使用返回的浏览器身份信息提交 Solution.Token。将此目标传输层与 SDK 客户端的 solvethree API 传输层分开。
本页内容
准备任务
- 1.
设置 Go SDK 和凭据
使用版本为
v0.1.0的官方solvethree.com/sdk模块,以及 Go 1.22 或更高版本。设置详情请参阅 Go 集成参考文档。将SOLVETHREE_API_KEY设为工作区 API 密钥,并将其保留在服务器端。将SOLVETHREE_PROXY设为 HTTP 或 HTTPS 代理 URL。 - 2.
求解前配置站点
工作区中需要有目标主机名的有效配置。请先设置站点配置;提交主机名和操作不会创建配置。
- 3.
替换示例目标
更改
accounts.example.com、login操作和应用端点,使其符合你的集成。Site是主机名,而不是完整 URL。对于 reCAPTCHA,必须且只能提供Proxy或ProxyCandidates其中之一;不要填写任务的Type或URL字段。默认的 reCAPTCHA 类型为 Enterprise v3。
通过成功求解任务的代理提交
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 请求头发送代理凭据。
保留原始任务输入,即使目前只提供一个代理,也应使用 SuccessfulProxy。使用 ProxyCandidates 时,Solution.EgressAttempts 标识成功的候选代理,它是原始列表中从 1 开始的索引。此辅助函数可避免猜测哪个候选代理成功;如果它返回 false,请停止。候选列表最多接受十二个不同的 HTTP 或 HTTPS 代理 URL,且不得包含路径、查询参数或片段。
包含目标站点的请求头、表单字段和会话
此示例使用 url.Values,将 Solution.Token 以 g-recaptcha-response 为字段名进行表单编码,并设置匹配的内容类型。如果应用期望其他字段名,请替换该名称。添加端点要求的其他字段,例如登录输入和任何与会话绑定的防 CSRF 值;CAPTCHA 令牌并不是完整的登录请求。
像示例一样,使用返回的 UserAgent 和 SecChUA。如果解决结果还在 Headers 中提供了条目,也应将这些返回的请求头应用于目标请求——示例并未复制该集合。保持浏览器身份一致,并确保内容类型与发送的请求体相符。
此示例没有 Cookie 容器。如果目标站点需要会话,请使用 net/http/cookiejar 创建容器,在启动目标站点流程之前将其附加到 targetClient.Jar,并在页面请求和表单提交中复用该客户端。整个会话期间使用同一个成功的代理。solvethree API 客户端不是目标站点的会话客户端。
读取解决结果前,先检查求解错误。只有就绪任务才有可用的解决结果;失败任务的 errorCode 和 error 会说明失败原因。对于目标请求,先处理 Do 返回的错误,再检查 HTTP 状态,最后解析响应体。只要 Do 返回了响应且没有错误,就必须关闭 response.Body,包括 HTTP 状态表示不成功的响应。
该示例禁用自动重定向,并打印应用状态。请检查响应体和任何预期的重定向,以判断应用是否接受了提交。任务就绪或仅有成功的 HTTP 状态,都不能证明提交已被接受。
运行您的第一个任务。
使用 $5 工作区额度开始体验。