So lösen Sie GeeTest v3 in Python und senden es zurück

solve geetest in python - How to Solve GeeTest v3 in Python and Post It Back

Der meiste Captcha-Code geht von einem Token rein, einem Token raus aus. GeeTest durchbricht das. Eine Lösung gibt zurück drei Werte, die zusammen abgesendet werden müssen, und die Challenge, die Sie eingegeben haben, läuft etwa sechzig Sekunden nach dem Abrufen ab. Beides bringt Nutzer zu Fall, und keines davon scheitert mit einer hilfreichen Meldung.

Zwei Eingaben, die sich unterschiedlich verhalten

WertLifetime
gtStatisch für die Website. Cachen Sie ihn beliebig
challengeEinmalige Verwendung, nach etwa 60 Sekunden tot

Beide stammen vom eigenen GeeTest-Init-Endpunkt der Website. Der gt ist praktisch eine Website-Kennung. Der challenge gilt pro Versuch, und ihn als wiederverwendbar zu behandeln, ist der mit Abstand häufigste Grund, warum eine GeeTest-Integration im Test funktioniert und unter Last auseinanderfällt.

Einrichtung

# Python 3.10 or newer.
pip install capskip
from capskip import CapSkip

solver = CapSkip(
    host="127.0.0.1",
    port=8080,
    recaptchaTimeout=300,   # GeeTest uses this, not defaultTimeout
)

Diese Timeout-Unterscheidung wird leicht übersehen. defaultTimeout regelt nur Bild-Captchas; alles Interaktive verwendet recaptchaTimeout.

Wird gelöst

result = solver.geetest(
    gt="81388ea1fc187e0c335c0a8907ff2625",
    challenge="7cf6a8b1a2c34d5e6f7089abcdef0123",
    url="https://example.com/login",
)

print(result["challenge"])
print(result["validate"])
print(result["seccode"])

Diese drei Schlüssel sind die Antwort. result["code"] wird ebenfalls befüllt, aber bei GeeTest enthält es die rohe JSON-Zeichenfolge und nicht etwas, das Sie absenden können, sodass ein gewohnheitsmäßiger Griff danach zu einem verwirrenden Fehler führt.

Verwenden Sie den challenge das zurückkommt, nicht das, das Sie eingesendet haben. Sie sind nicht immer derselbe Wert.

Der vollständige Ablauf, an einem Ort

Abrufen und Lösen müssen benachbart sein. Alles Langsame dazwischen riskiert den Ablauf:

import time
import requests
from capskip import CapSkip

solver = CapSkip()
LOGIN = "https://example.com/login"

# 1. Fresh pair, cache-busted. Cached init responses hand back dead challenges.
init = requests.get(
    "https://example.com/geetest/init",
    params={"t": int(time.time() * 1000)},
).json()

# 2. Solve immediately. Do not queue this.
result = solver.geetest(gt=init["gt"], challenge=init["challenge"], url=LOGIN)

# 3. Post all three together, alongside the real form fields.
response = requests.post(LOGIN, data={
    "geetest_challenge": result["challenge"],
    "geetest_validate": result["validate"],
    "geetest_seccode": result["seccode"],
    "username": "...",
    "password": "...",
})

Der Cache-Busting-Zeitstempel ist wichtiger, als er aussieht. GeeTest-Init-Endpunkte werden oft von einem CDN oder Proxy gecacht, und eine gecachte Antwort liefert Ihnen eine Challenge, die bereits verbraucht war.

Diese drei Feldnamen sind die übliche GeeTest v3-Konvention, aber eine Website kann sie umbenennen. Prüfen Sie das echte Formular, bevor Sie etwas annehmen.

Mehrere gleichzeitig bearbeiten

Die Falle hier ist falsches Batching. Einen Stapel von Challenges abzurufen und sie dann alle zu lösen, garantiert, dass die späteren ablaufen, bevor sie an der Reihe sind. Abrufen und lösen Sie innerhalb derselben Aufgabe:

import asyncio
from capskip import AsyncCapSkip

async def solve_one(solver, url):
    init = await fetch_pair(url)          # your own fetch, awaited
    return await solver.geetest(
        gt=init["gt"], challenge=init["challenge"], url=url,
    )

async def main():
    solver = AsyncCapSkip()
    return await asyncio.gather(*[solve_one(solver, u) for u in urls])

asyncio.run(main())

Python ist das einzige CapSkip-SDK, bei dem AsyncCapSkip ist ein echter Async-Client und kein Alias, sodass dies Lösungen tatsächlich parallel ausführt.

Wenn es fehlschlägt

from capskip import (
    ValidationException, NetworkException, ApiException, TimeoutException,
)

try:
    result = solver.geetest(gt=gt, challenge=challenge, url=page_url)
except ValidationException:
    pass   # missing gt or challenge
except NetworkException:
    pass   # CapSkip is not running
except ApiException:
    pass   # usually a challenge that expired before the solve finished
except TimeoutException:
    pass   # exceeded recaptchaTimeout

In der Praxis treten die meisten GeeTest-Fehler auf als ApiException und bedeuten, dass die Challenge gestorben ist. Die Lösung besteht darin, später abzurufen, nicht dieselbe Kombination erneut zu versuchen, denn eine verbrauchte Challenge wird nie wieder gültig.

Häufig gestellte Fragen

Warum ist result[“code”] nicht verwendbar?

Weil die Antwort aus drei Werten statt einem besteht. code behält das rohe JSON zur Vollständigkeit, während das SDK die nützlichen Teile erweitert zu challenge, validate und seccode. Reichen Sie diese drei ein.

Kann ich die Challenge zwischen Durchläufen cachen?

Nein. Er ist zur einmaligen Verwendung und läuft in etwa einer Minute ab. Der gt kann bedenkenlos zwischengespeichert werden; die Challenge niemals.

Deckt dies GeeTest v4 ab?

The geetest Methode zielt auf v3 ab, das Schiebepuzzle, das um ein gt und challenge Paar. v4 hat das Parametermodell geändert, prüfen Sie also das aktuelle API-Dokumentation bevor Sie annehmen, dass derselbe Aufruf gilt.

Zusammenfassung

Abrufen gt und challenge unmittelbar vor dem Lösen mit einer cache-busted Anfrage, rufen Sie geetest, dann senden Sie challenge, validate und seccode zusammen. Verwenden Sie die zurückgegebene Challenge statt Ihrer Eingabe und holen Sie Challenges niemals im Voraus in Batches vor dem Lösen.

Andere Sprachen finden Sie auf der GeeTest-Löser Seite, die breitere Python-Oberfläche auf der Python-Captcha-Löser Seite, und es gibt ein Live-Puzzle auf unserer GeeTest-v3-Demo. CapSkip übernimmt Captcha-Umgehung lokal, sodass das Lösevolumen kostenlos ist.