Das Go SDK mit chromedp verwenden
Lösen Sie zuerst die Aufgabe und starten Sie dann Chrome mit demselben Proxy und der zurückgegebenen Browseridentität. Fügen Sie das Token in das Formular der Anwendung ein, senden Sie es ab und warten Sie auf das Ergebnis der Anwendung. Eine bereite Aufgabe bedeutet, dass eine Lösung vorliegt – nicht, dass die Website sie akzeptiert hat.
Auf dieser Seite
Module, Profil und Proxy einrichten
Installieren Sie solvethree.com/[email protected] und github.com/chromedp/[email protected] mit go get. Das SDK erfordert Go 1.22+, diese chromedp-Version jedoch Go 1.25+. Verwenden Sie daher diese Version für das kombinierte Beispiel. Die typisierte API unterscheidet sich von älteren chromedp-Beispielen.
Erstellen Sie vor dem Ausführen des Programms ein aktives Websiteprofil für den Zielhostnamen in Ihrem Arbeitsbereich. Durch das Senden eines Hostnamens und einer Aktion wird kein Profil erstellt.
TARGET_URL: die vollständige HTTPS-Seiten-URL mit Ihrem Formular. Die Aufgabe verwendet deren Hostnamen alsSite; Chrome navigiert zur vollständigen URL.SOLVETHREE_PROXY: eine einzelne HTTP- oder HTTPS-Proxy-URL. Dieses Beispiel erfordert einen Proxy mit IP-Freigabeliste ohne Zugangsdaten in der URL.SOLVETHREE_API_KEY: der API-Schlüssel Ihres Arbeitsbereichs. Bewahren Sie ihn im Go-Prozess auf, nicht im JavaScript der Seite.
Das Beispiel fordert die Aktion login an und verwendet den standardmäßigen Enterprise-v3-reCAPTCHA-Modus. Ändern Sie die Aktion in den von Ihrer Anwendung erwarteten Wert.
Lösen, Chrome starten und absenden
Das Programm wartet auf den Lösungsvorgang des SDK, bevor es den Chrome-Allocator erstellt. Es konfiguriert Chrome mit demselben einzelnen Proxy und result.Solution.UserAgent und setzt anschließend vor der Navigation den zurückgegebenen Wert SecChUA als Header sec-ch-ua. Ersetzen Sie die Browseridentität nicht durch eine andere und wechseln Sie zwischen Lösungsvorgang und Übermittlung nicht den Proxy.
// go get github.com/chromedp/[email protected] (requires Go 1.25+)
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/url"
"os"
"time"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/chromedp"
solvethree "solvethree.com/sdk"
)
func main() { if err := run(); err != nil { log.Fatal(err) } }
func run() error {
target,err:=url.Parse(os.Getenv("TARGET_URL"));if err!=nil||target.Scheme!="https"||target.Hostname()=="" { return fmt.Errorf("set an HTTPS TARGET_URL") }
proxy,err:=url.Parse(os.Getenv("SOLVETHREE_PROXY"));if err!=nil||proxy.User!=nil { return fmt.Errorf("use an IP-allowlisted proxy without URL credentials") }
client,err:=solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"),nil);if err!=nil { return err }
ctx,cancel:=context.WithTimeout(context.Background(),180*time.Second);defer cancel()
result,err:=client.Solve(ctx,solvethree.TaskRequest{Site:target.Hostname(),Action:"login",Proxy:proxy.String()},solvethree.SolveOptions{})
if err!=nil { return err }
options:=append(chromedp.DefaultExecAllocatorOptions[:],chromedp.ProxyServer(proxy.String()),chromedp.UserAgent(result.Solution.UserAgent))
allocator,closeAllocator:=chromedp.NewExecAllocator(context.Background(),options...);defer closeAllocator()
browser,closeBrowser:=chromedp.NewContext(allocator);defer closeBrowser()
browser,stop:=context.WithTimeout(browser,60*time.Second);defer stop()
tokenJSON,err:=json.Marshal(result.Solution.Token);if err!=nil { return err }
script:=`(token => {const field=document.querySelector('[name="g-recaptcha-response"]'); field.value=token; field.dispatchEvent(new Event('input',{bubbles:true}));})(`+string(tokenJSON)+`)`
_,err=chromedp.Call(browser,network.SetExtraHTTPHeaders,network.SetExtraHTTPHeadersParams{Headers:network.Headers{"sec-ch-ua":result.Solution.SecChUA}})
if err!=nil { return err }
err=chromedp.Do(browser,
chromedp.Navigate(target.String()),chromedp.WaitReady(chromedp.CSS(`[name="g-recaptcha-response"]`)),
chromedp.Evaluate[chromedp.Void](script),chromedp.Click(chromedp.CSS(`button[type="submit"]`)),
chromedp.WaitVisible(chromedp.ID("success")))
if err!=nil { return err }
// #success is this owned demo form's outcome. Adapt its selectors, token
// parameter and success check to your application, including CSRF/session fields.
return nil
}Dieses Beispiel verwendet bewusst einen einzigen Proxy, sodass keine Kandidatenauswahl aufgelöst werden muss. Wenn Sie später ProxyCandidates verwenden, ermitteln Sie den erfolgreichen Proxy mit SuccessfulProxy(originalTask, readyResult) und verwenden Sie diesen Proxy für Chrome.
Annahmen zum Demoformular ersetzen
Beim Einfügen des Tokens wird json.Marshal verwendet, bevor der JavaScript-Ausdruck erstellt wird. Behalten Sie diesen Escape-Schritt bei: Er übergibt das Token als JavaScript-Zeichenfolgenwert, statt Text ohne Escape-Behandlung in ausführbaren Code einzufügen.
- Ersetzen Sie
[name="g-recaptcha-response"]durch das Feld, das Ihre Anwendung tatsächlich übermittelt. Das Beispiel setzt dessen Wert und löst ein input-Ereignis aus; passen Sie dies an, wenn Ihre Anwendung einen anderen Übermittlungsweg benötigt. - Ersetzen Sie
button[type="submit"]durch das vorgesehene Absendeelement. Fügen Sie vor dem Klicken alle erforderlichen Formularwerte, CSRF-Felder und den Sitzungszustand hinzu. - Ersetzen Sie
#successdurch ein Ergebnis, das in Ihrer Anwendung tatsächlich eine Annahme signalisiert. Ein abgeschlossener Klick oder ein ausgefülltes Token-Feld ist kein solches Ergebnis.
Das SDK übermittelt das Token nicht an das Ziel. Wenn das Ziel die Anfrage ablehnt, prüfen Sie zuerst das ausgehende Formular: Stellen Sie sicher, dass es result.Solution.Token enthält, nicht die Aufgaben-ID oder einen älteren Feldwert, und prüfen Sie, ob Proxy und Browseridentität weiterhin übereinstimmen.
Zeitlimits ohne doppelte Lösungsvorgänge behandeln
Für den Lösungsvorgang gilt ein Kontext-Zeitlimit von 180 Sekunden. Chrome erhält nach dem Lösen ein separates Zeitlimit von 60 Sekunden. Die Funktion run gibt Fehler zurück, sodass der verzögerte Kontextabbruch und die Browserbereinigung ausgeführt werden, bevor main einen Fehler protokolliert.
Das Abbrechen des Lösungskontexts beendet das Warten, nicht die entfernte Verarbeitung. Das SDK erstellt die Aufgabe einmal und wiederholt nur vorübergehend fehlgeschlagene Statusabfragen; den POST zum Erstellen wiederholt es nie. Ein Timeout ist daher kein Grund, sofort eine neue Aufgabe zu übermitteln.
- Verwenden Sie bei einem Abbruch oder überschrittenen Zeitlimit
errors.Is, um den Kontextfehler zu identifizieren. Extrahieren Sie*solvethree.Errormiterrors.Asund bewahren Sie dessenTaskIDundRequestIDauf. - Wenn Sie eine Aufgaben-ID haben, rufen Sie die Aufgabe mit
GetTaskab. Andernfalls stellen Sie sie wieder her, indem Sie exakt dieselben ursprünglichen Aufgabeneingaben mit derselben Anfrage-ID erneut senden. Ein erneuter Aufruf ohne diese ID erstellt eine neue logische Anfrage; geänderte Eingaben bei Wiederverwendung der ID führen zu einem Konflikt. - Prüfen Sie bei
*TaskFailedErrorden WertErrorCodeund rufen Sie die fehlgeschlagene Aufgabe ab, um ihren Fehlertext zu erhalten. Diese Aufgabe ist endgültig fehlgeschlagen: Beenden Sie die Statusabfragen und beheben Sie die Ursache, statt es mit unveränderten Eingaben erneut zu versuchen. - Extrahieren Sie bei einem HTTP-API-Fehler den verschachtelten
*APIError, umStatusCodeundRetryAfterzu prüfen. Verwechseln Sie einen HTTP-Fehler nicht mit einer endgültig fehlgeschlagenen Aufgabe.
Quellen und API-Referenz
Führe deinen ersten Task aus.
Starte mit $5 Workspace-Guthaben.