פתרון reCAPTCHA Enterprise באמצעות Java

מאת solvethree2 דקות קריאה

השתמשו ב־HttpClient של Java כדי לבקש אסימון וב־Gson כדי לקרוא את תגובת ה־JSON. הדוגמה הזו קוראת ל־REST API, ממתינה לסיום המשימה ומחזירה את פתרון ה־reCAPTCHA Enterprise.

בדף הזה

הגדרת האתר והסביבה

השתמשו ב־Java 21 ומעלה. צרו במסוף פרופיל אתר פעיל עבור היעד שלכם, ואז הגדירו את SOLVETHREE_API_KEY ואת SOLVETHREE_PROXY בסביבה שמפעילה את Java.

החליפו את accounts.example.com בשם המארח שעבורו הגדרתם פרופיל, ואת login בפעולה שבה הדף משתמש. השדה site מקבל שם מארח, ללא סכמה או נתיב.

שמירה והרצה של Solve.java

Java 21+ · Solve.java (תלות ב-Gson)
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.UUID;

public class Solve {
    static final HttpClient HTTP = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(15)).build();
    static final String KEY = System.getenv("SOLVETHREE_API_KEY");

    static JsonObject api(String path, JsonObject body, long deadline) throws Exception {
        long remaining = deadline - System.nanoTime();
        if (remaining <= 0) throw new IllegalStateException("Keep the task ID and resume polling");
        var builder = HttpRequest.newBuilder(URI.create("https://api.solvethree.com/v1" + path))
            .timeout(Duration.ofNanos(Math.min(remaining, Duration.ofSeconds(30).toNanos())))
            .header("Authorization", "Bearer " + KEY)
            .header("Content-Type", "application/json");
        if (body == null) builder.GET();
        else builder.POST(HttpRequest.BodyPublishers.ofString(body.toString()));
        var response = HTTP.send(builder.build(), HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() < 200 || response.statusCode() >= 300)
            throw new IllegalStateException("API HTTP " + response.statusCode());
        return JsonParser.parseString(response.body()).getAsJsonObject();
    }
    public static void main(String[] args) throws Exception {
        String proxy = System.getenv("SOLVETHREE_PROXY");
        if (KEY == null || proxy == null) throw new IllegalArgumentException("Set the API key and proxy");
        var input = new JsonObject();
        input.addProperty("site", "accounts.example.com");
        input.addProperty("action", "login");
        input.addProperty("proxy", proxy);
        input.addProperty("requestId", UUID.randomUUID().toString());
        // Save input before creation if the task must be recovered after restart.
        long deadline = System.nanoTime() + Duration.ofSeconds(180).toNanos();
        var task = api("/tasks?waitMs=0", input, deadline);
        while (task.get("status").getAsString().equals("pending") || task.get("status").getAsString().equals("solving")) {
            String id = URLEncoder.encode(task.get("id").getAsString(), StandardCharsets.UTF_8);
            task = api("/tasks/" + id + "?waitMs=15000", null, deadline);
            if (task.get("status").getAsString().equals("pending") || task.get("status").getAsString().equals("solving"))
                Thread.sleep(1000);
        }
        if (!task.get("status").getAsString().equals("ready"))
            throw new IllegalStateException("Task failed: " + task.get("errorCode")
                + ": " + task.get("error"));
        var solution = task.getAsJsonObject("solution");
        // Submit solution.token with userAgent/secChUa and the original proxy.
        System.out.println("Ready task: " + task.get("id").getAsString());
    }
}

מתוך התיקייה שמכילה את Solve.java, הורידו את קובץ ה־JAR של Gson, הידרו והריצו:

macOS/Linux · הורדת Gson והרצת Solve.java
curl --fail --location --output gson-2.15.0.jar \
  https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.15.0/gson-2.15.0.jar
javac -cp gson-2.15.0.jar Solve.java
java -cp .:gson-2.15.0.jar Solve

הפקודות האלה משתמשות במפריד ה־classpath של macOS/Linux, שהוא :. ב־Windows, השתמשו ב־; בין התיקייה הנוכחית לקובץ ה־JAR של Gson.

קריאת האסימון מהתוצאה

היצירה משתמשת ב־waitMs=0. הלולאה מאחזרת את אותו מזהה משימה כל עוד המצב הוא pending או solving, ועוצרת במצב ready או failed. כל בקשת GET יכולה להמתין עד 15 שניות; לקוד הקורא מוקצות 180 שניות בסך הכול.

קראו את האסימון באמצעות solution.get("token").getAsString(). השתמשו ב־userAgent וב־secChUa שהוחזרו בבקשה ליעד, דרך אותו פרוקסי. התוכנית מדפיסה את מזהה המשימה, לא את האסימון.

בדקו את תגובת היעד לאחר השליחה. משימה מוכנה מעידה שנוצר פתרון; היא אינה מעידה שהיישום קיבל אותו.

שגיאות ובקשות שנקטעו

פונקציית העזר עוצרת בתגובת HTTP שאינה מציינת הצלחה. משימה שנכשלה באופן סופי מדווחת על errorCode ועל error, וניתן החזר על הפתרון שנכשל. השתמשו במדריך שגיאות ה־API כדי להחליט מה לתקן.

שמרו את ה־requestId שנוצר ואת הקלט המדויק אם תזדקקו לשחזור לאחר הפעלות מחדש. אם היצירה חורגת ממגבלת הזמן, שלחו שוב את הקלט הזה עם אותו מזהה. אם כבר יש לכם מזהה משימה, אחזרו אותה. הפעלה מחדש של התוכנית הזו יוצרת UUID אחר ועלולה ליצור משימה נוספת בתשלום.

הפעלת המשימה הראשונה שלך.

התחילו עם $5 בקרדיט לסביבת העבודה.

יצירת סביבת עבודה
פתרון reCAPTCHA Enterprise באמצעות Java · solvethree