C# में GeeTest v3 कैसे हल करें

solve geetest in c# - How to Solve GeeTest v3 in C# and Post the Result Back

GeeTest उस मानसिक मॉडल को तोड़ देता है जिस पर अधिकांश कैप्चा code बना होता है। किसी form field में डालने के लिए कोई एकल token नहीं होता। एक हल लौटाता है तीन वैल्यू जिन्हें एक साथ वापस पोस्ट करना होता है, और जिस challenge से आपने शुरू किया था वह लगभग एक मिनट में समाप्त हो जाता है। कोई भी हिस्सा गलत करें और request बिना किसी उपयोगी त्रुटि के फेल हो जाती है।

यहाँ C# में पूरा flow है, उन हिस्सों सहित जिन्हें ग़लत करना आसान है।

दो inputs, और उनमें से केवल एक स्थिर है

GeeTest v3 एक साइट को इससे पहचानता है gt और इसके साथ एक अकेला प्रयास challenge। वे पूरी तरह अलग तरीके से व्यवहार करते हैं।

Valueआजीवनयह कहाँ से आता है
gtसाइट के लिए स्थिर। hard-code या कैश करना सुरक्षितsite की GeeTest init response
challengeSingle use, लगभग 60 सेकंड में समाप्त हो जाता हैवही init response, हर बार ताज़ा

वह expiry GeeTest विफलताओं का सबसे आम एकल कारण है। अगर आप एक pair fetch करते हैं, job को queue में डालते हैं, और उसे तीस सेकंड बाद दूसरे काम के पीछे हल करते हैं, तो challenge शायद पहले ही मर चुका हो। हल करने से ठीक पहले उसे fetch करें, कभी cache से नहीं।

Setup

# Targets .NET Standard 2.0, so Framework 4.6.1+ and .NET 6-9 all work.
dotnet add package CapSkip

CapSkip आपकी अपनी मशीन पर चलता है, इसलिए पहले app शुरू करें और client को उसकी settings से मिले port पर इंगित करें:

using CapSkip;

var solver = new CapSkipClient(
    apiKey: "capskip",        // any string when key validation is off
    host: "127.0.0.1",
    port: 8080,
    recaptchaTimeout: 300);   // seconds, and this one covers GeeTest too

ध्यान दें कि GeeTest उपयोग करता है recaptchaTimeout, नहीं defaultTimeout। बाद वाला सिर्फ़ image कैप्चा पर लागू होता है।

इसे हल करना

तीन स्थितीय आर्गुमेंट, इस क्रम में:

var result = await solver.GeetestAsync(
    "81388ea1fc187e0c335c0a8907ff2625",   // gt, static per site
    "7cf6a8b1a2c34d5e6f7089abcdef0123",   // challenge, fetched seconds ago
    "https://example.com/login");

Console.WriteLine(result.Challenge);
Console.WriteLine(result.Validate);
Console.WriteLine(result.Seccode);

वे तीन प्रॉपर्टीज़ ही जवाब हैं। result.Code भी भरा जाता है, लेकिन GeeTest के लिए यह किसी उपयोग योग्य token के बजाय raw JSON string रखता है, इसलिए इसकी ओर जाना Code आदतन ऐसा करना एक गलती है। On SolveResult, Challenge, Validate और Seccode केवल GeeTest के लिए हैं और हर दूसरे प्रकार के लिए null हैं।

जानने लायक: यह challenge जो वापस आता है वह हमेशा वही नहीं होता जो आपने भेजा था। अपने input के बजाय लौटाई गई value का उपयोग करें।

जवाब वापस पोस्ट करना

तीनों को ठीक वैसे ही सबमिट करें जैसे साइट’s का अपना फ़्रंट एंड करता। ज़्यादातर GeeTest v3 इंटीग्रेशन इन field नामों का इस्तेमाल करते हैं, हालाँकि कोई साइट इन्हें बदल सकती है, इसलिए मान लेने से पहले असली फ़ॉर्म जाँचें:

using System.Net.Http;
using System.Collections.Generic;

using var http = new HttpClient();

var form = new FormUrlEncodedContent(new[]
{
    new KeyValuePair<string, string>("geetest_challenge", result.Challenge),
    new KeyValuePair<string, string>("geetest_validate",  result.Validate),
    new KeyValuePair<string, string>("geetest_seccode",   result.Seccode),
    new KeyValuePair<string, string>("username", "..."),
    new KeyValuePair<string, string>("password", "..."),
});

var response = await http.PostAsync("https://example.com/login", form);

तीन में से दो भेजना, या एक ताज़ा को जोड़ना validate एक बासी के साथ challenge, उसी तरह अस्वीकृत हो जाता है जैसे एक गलत answer होगा।

पूरा flow, क्रम में

जोड़ी को fetch करना और हल करना एक-दूसरे के बगल में होने ही चाहिए। यह संरचना उन्हें वहाँ बनाए रखती है:

using System;
using System.Net.Http;
using System.Text.Json;
using CapSkip;

// 1. Fetch a fresh gt/challenge pair from the site's own init endpoint.
using var http = new HttpClient();
var initJson = await http.GetStringAsync(
    "https://example.com/geetest/init?t=" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());

using var doc = JsonDocument.Parse(initJson);
var gt        = doc.RootElement.GetProperty("gt").GetString();
var challenge = doc.RootElement.GetProperty("challenge").GetString();

// 2. Solve immediately. Do not queue this or await anything slow in between.
var result = await solver.GeetestAsync(gt, challenge, "https://example.com/login");

// 3. Post all three values together.
Console.WriteLine($"{result.Challenge} {result.Validate} {result.Seccode}");

init call पर cache-busting timestamp जितना दिखता है उससे ज़्यादा मायने रखता है। GeeTest init endpoints को अक्सर intermediaries cache कर लेते हैं, और एक cached response आपको ऐसा challenge थमा देता है जो पहले ही इस्तेमाल हो चुका था।

जब यह फेल होता है

using System;
using CapSkip;

try
{
    var result = await solver.GeetestAsync(gt, challenge, pageUrl);
}
catch (CapSkip.ValidationException) { /* missing gt or challenge */ }
catch (NetworkException)            { /* CapSkip is not running */ }
catch (ApiException)                { /* API error, often a dead challenge */ }
catch (CapSkip.TimeoutException)    { /* exceeded recaptchaTimeout */ }
catch (CapSkipError)                { /* anything else from the SDK */ }

Qualify ValidationException और TimeoutException इसके साथ CapSkip namespace। दोनों नाम इसमें भी मौजूद हैं System, और दोनों namespaces import होने पर एक unqualified catch इससे बंध जाता है System प्रकार और चुपचाप कभी फ़ायर नहीं होता। base को catch करना CapSkipError समस्या को पूरी तरह टाल देता है।

व्यवहार में अधिकांश GeeTest failures इस रूप में सामने आती हैं ApiException और इसका मतलब है कि हल पूरा होने से पहले challenge मर गया। इसका फ़िक्स बाद में fetch करना है, वही values के साथ दोबारा कोशिश करना नहीं।

प्रॉक्सी और concurrency

GeeTest उन तीन प्रकारों में से एक है जो प्रॉक्सी स्वीकार करते हैं, reCAPTCHA और Turnstile के साथ। Image कैप्चा नहीं करते, क्योंकि वे कभी टारगेट साइट को छूते ही नहीं।

using System.Collections.Generic;

var result = await solver.GeetestAsync(gt, challenge, pageUrl,
    new Dictionary<string, object?>
    {
        ["proxy"] = new Proxy("HTTPS", "user:[email protected]:3128"),
    });

कई को parallel में चलाना काम करता है, पर हर एक को अपना ताज़ा fetch किया गया pair चाहिए। पहले से challenges का एक batch fetch करके उन्हें एक साथ हल न करें, क्योंकि आख़िरी वाले अपनी बारी से पहले ही expire हो चुके होंगे।

// Correct: fetch and solve inside the same task.
var tasks = urls.Select(async url =>
{
    var (gt, challenge) = await FetchPairAsync(url);
    return await solver.GeetestAsync(gt, challenge, url);
});

var results = await Task.WhenAll(tasks);

अक्सर पूछे जाने वाले सवाल

result.Code एक उपयोग करने योग्य token क्यों नहीं है?

क्योंकि GeeTest का जवाब तीन values हैं, एक नहीं। Code पूर्णता के लिए raw JSON string रखता है, जबकि SDK काम के हिस्सों को इसमें विस्तृत कर देता है Challenge, Validate और Seccode. उन तीनों का उपयोग करें।

क्या मैं एक request बचाने के लिए challenge को cache कर सकता हूँ?

नहीं। यह single use है और लगभग एक मिनट में एक्सपायर हो जाता है। इसे cache करना सबसे आम वजह है कि GeeTest integrations testing में काम करते हैं और load में नाकाम हो जाते हैं, क्योंकि queueing delay हल को expiry window के पार धकेल देती है। The gt वैल्यू cache करना सुरक्षित है।

क्या यह GeeTest v4 के लिए काम करता है?

The GeetestAsync method v3 को लक्षित करता है, वह slide-puzzle संस्करण जो इसके आसपास बना है the gt और challenge जोड़ी। v4 ने पैरामीटर model बदल दिया, इसलिए मौजूदा जांचें API डॉक्युमेंटेशन यह मानने से पहले कि वही कॉल काम करती है, देखें कि क्या समर्थित है।

क्या मुझे प्रॉक्सी चाहिए?

सिर्फ़ तब जब site geo-sensitive हो या पहले से ही आपके address को संदिग्ध मानती हो। जब आप किसी का उपयोग करें तो एक ही network path से हल करें और सबमिट करें, वरना बेमेल खुद ही एक re-challenge ट्रिगर कर सकता है।

सारांश

Fetch gt और challenge हल करने से ठीक पहले, कॉल करें GeetestAsync दोनों के साथ तथा page URL के साथ, फिर post करें Challenge, Validate और Seccode वापस एक साथ। challenge को नाशवान मानें, अपने input के बजाय लौटाए गए challenge का उपयोग करें, और पकड़ें CapSkipError namespace टकराव से बचने के लिए।

अन्य भाषाओं के लिए method signatures इस पर हैं GeeTest solver page, पूरा .NET surface यहाँ है C# कैप्चा सॉल्वर पेज, और आप हमारे यहाँ एक लाइव पहेली आज़मा सकते हैं GeeTest v3 demo। CapSkip संभालता है कैप्चा बायपास लोकल रूप से, इसलिए हल की मात्रा की प्रति request कोई लागत नहीं।