hrequests में कैप्चा कैसे हल करें (Python TLS Client)

hrequests captcha - How to Solve CAPTCHAs in hrequests (Python TLS Client)

hrequests में कैप्चा हल छोटा होता है, क्योंकि कैप्चा पढ़ने वाला हिस्सा hrequests है ही नहीं। यह requests को एक Go TLS client के ज़रिए भेजता है ताकि आपका handshake किसी असली Chrome या Firefox जैसा दिखे, और इससे आप उस जाँच से पार निकल जाते हैं जो किसी challenge के बनने से पहले ही चल जाती है। जब site फिर भी कोई challenge दिखा देती है, तो आपको कुछ ऐसा चाहिए जो किसी sitekey को token में बदल दे। असली ध्यान देने लायक़ हिस्सा इन दोनों के बीच का है: token को उसी session पर वापस जाना चाहिए जिसने page लाया था, किसी नए session पर नहीं।

आपको क्या चाहिए

  • Python 3.10 या उससे नया, जिसमें hrequests इंस्टॉल हो। browser extra तभी जोड़ें जब आपको वाकई render करने की ज़रूरत हो।
  • एक Windows machine पर चलता हुआ CapSkip। अगर script उसी machine पर चलती है तो Local mode, और कहीं और चलती है तो Server mode।
  • sitekey और page URL। Step 1 sitekey को hardcode करने के बजाय उसे page से निकालता है।
  • एक प्रॉक्सी, अगर target को आपके handshake के साथ-साथ आपके IP की भी परवाह है। hrequests इसे एक URL string के रूप में लेता है।
# pip install capskip
pip install -U hrequests capskip

# Only if you need the browser. It downloads a browser build.
pip install -U hrequests[all]
python -m hrequests install

दो अलग तरह के block, दो अलग tools

इस बारे में साफ़-साफ़ कहना ज़रूरी है, क्योंकि इन दोनों को लगातार गड्डमड्ड किया जाता है। hrequests browser TLS fingerprints की नक़ल करता है और उनसे मेल खाते headers बनाता है। यह न किसी तस्वीर को देखता है और न ही कोई reCAPTCHA token बनाता है। CapSkip tokens बनाता है और आपके TLS fingerprint को छूता तक नहीं। किसी challenge के दिखने से पहले ही block हो जाना एक handshake की समस्या है, और इसकी गाइड Python में TLS fingerprinting उसी के लिए लिखी गई है। कोई challenge दिखाया जाना ही वह बात है जिसके बारे में इस page का बाक़ी हिस्सा है।

hrequests के documentation की एक बात browser चुनने से पहले जान लेना फ़ायदेमंद है। Session बनाते समय एक browser argument लिया जाता है जो firefox या chrome स्वीकार करता है, और README का विवरण तथा उसकी parameter table इस पर आपस में असहमत हैं कि डिफ़ॉल्ट रूप से आपको कौन-सा मिलता है। इसे साफ़-साफ़ पास कर दें और यह उलझन ख़त्म हो जाती है।

Step 1: page लाएँ और sitekey निकालें

किसी नंगे get के बजाय एक session इस्तेमाल करें, क्योंकि session ही cookies इकट्ठा करता है और उसी के ज़रिए आप token वापस post करेंगे। hrequests response पर एक तेज़ HTML parser देता है, इसलिए आप sitekey का अंदाज़ा लगाने के बजाय उसे markup से पढ़ सकते हैं।

# pip install hrequests
import hrequests

SITE = "https://example.com/page-with-recaptcha"

# Name the browser. Headers are generated to match it and the OS.
session = hrequests.Session(browser="chrome", os="win")

resp = session.get(SITE)

# The parser is selectolax under the hood, so this is cheap.
widget = resp.html.find(".g-recaptcha")
sitekey = widget.attrs["data-sitekey"]

print(resp.status_code, sitekey)

अगर widget शुरुआती HTML में नहीं है, तो उसे JavaScript inject कर रहा है और आपको एक render की ज़रूरत है। हालाँकि उसकी ओर बढ़ने से पहले नीचे वाला browser section देखें, क्योंकि ज़्यादातर reCAPTCHA और Turnstile widgets परोसे गए markup में ही होते हैं और render करने पर आपको बेवजह एक browser process ख़र्च करना पड़ता है।

Step 2: इसे CapSkip से हल करें

एक ही call। SDK challenge submit करता है और जवाब के लिए poll करता है, 250 milliseconds से शुरू करके धीमा होता हुआ, यही वजह है कि यह आम तौर पर raw API के ख़िलाफ़ हाथ से लिखे loop को मात दे देता है।

# pip install capskip
from capskip import CapSkip

# 127.0.0.1 only if this script runs on the solver machine.
solver = CapSkip(host="127.0.0.1", port=8080)

result = solver.recaptcha(sitekey=sitekey, url=SITE)

token = result["code"]   # the g-recaptcha-response value

CapSkip जिस भी दूसरे प्रकार को सपोर्ट करता है उसकी शक्ल यही है। invisible या enterprise को 1 पर सेट करके जोड़ें, या version को किसी action name के साथ v3 पर सेट करें। Turnstile और GeeTest के अपने methods हैं, और Turnstile वही है जिसके notes पढ़ने चाहिए, क्योंकि किसी challenge page को दो अतिरिक्त values और उस user agent की ज़रूरत होती है जो token के साथ वापस आता है। वे अतिरिक्त values यहाँ कवर की गई हैं Cloudflare Turnstile सॉल्वर पेज। हर प्रकार का हर parameter यहाँ दिया गया है CapSkip API डॉक्यूमेंटेशन.

Step 3: token को उसी session पर post करें

यही वह step है जिसे लोग ग़लत करते हैं, और किसी सादे HTTP client के बजाय hrequests इस्तेमाल करने की पूरी वजह भी यही है। जिस session ने page लाया था उसका एक TLS fingerprint है, एक बनाया हुआ header set है और वे सारी cookies हैं जो site ने दी थीं। token को उसी session के ज़रिए post करें और submission ऐसा लगता है जैसे वह उसी client से आया हो। इसे किसी नए session के ज़रिए post करें, या उससे भी बुरा, standard library के ज़रिए, तो handshake बीच flow में बदल जाता है, जो अपने आप में एक signal है।

# Same session object, so the fingerprint, headers and cookies
# are the ones the site already saw on the GET.
posted = session.post(
    SITE,
    data={
        "username": "YOUR_USERNAME",
        "g-recaptcha-response": token,
    },
    timeout=30,
)

print(posted.status_code)
session.close()

यह तुरंत करें। कोई reCAPTCHA token लगभग दो मिनट तक वैध रहता है, इसलिए हल और post के बीच जो कुछ भी बैठता है वह उसी बजट को ख़र्च करता है। विफलता ऐसी दिखती है जैसे token को बिना किसी वजह अस्वीकार कर दिया गया हो, और अगर आप इससे टकराते हैं तो यह कहीं और पूरे विस्तार से लिखी गई है।

hrequests में request timeout डिफ़ॉल्ट रूप से 30 सेकंड होता है। यह यहाँ ठीक है, क्योंकि यह form post को कवर करता है, हल को नहीं। हल की अपनी सीमा SDK में है: image कैप्चा के लिए 120 सेकंड और reCAPTCHA, Turnstile तथा GeeTest के लिए 300।

सॉल्वर को किसी दूसरी मशीन पर चलाना

ऊपर दिया गया host argument ही एकमात्र चीज़ है जो तब बदलती है जब script और सॉल्वर एक ही machine साझा करना बंद कर देते हैं। CapSkip के दो connection modes हैं। Local mode 127.0.0.1 से bind होता है और सिर्फ़ उसी device को सेवा देता है। Server mode आपके network address या public IP से bind होता है, ताकि किसी दूसरे box, किसी VPS या किसी container पर चलने वाला स्क्रैपर उसी Windows machine तक API के ज़रिए पहुँच सके। दोनों यहाँ मौजूद हैं कनेक्शन सेटिंग्स, और अगर caller आपके network के बाहर है तो एक static public IP रखना फ़ायदेमंद है। Server mode सिर्फ़ यह बदलता है कि सॉल्वर किस address पर सुनता है: वही hardware, वही machine, वही बिना मीटर वाला हल।

import os
from capskip import CapSkip

# Same script on a laptop and on a scraping box. The env var
# decides; CAPSKIP_HOST and CAPSKIP_PORT are read by the SDK too.
solver = CapSkip(
    host=os.environ.get("CAPSKIP_HOST", "127.0.0.1"),
    port=8080,
)

प्रॉक्सी का ज़िक्र यहाँ ज़रूरी है, क्योंकि hrequests और CapSkip उन्हें अलग-अलग लेते हैं। आप hrequests को जो प्रॉक्सी देते हैं वह तय करती है कि आपका page fetch कहाँ से आता है। आप सॉल्वर को जो प्रॉक्सी देते हैं वह तय करती है कि challenge कहाँ से हल किया जाता है, और CapSkip reCAPTCHA, Turnstile तथा GeeTest के लिए एक प्रॉक्सी स्वीकार करता है, पर image कैप्चा के लिए नहीं। उन साइटों पर दोनों का मेल मायने रखता है जो किसी token को किसी address से बाँध देती हैं, और इसकी वजह यहाँ रखी गई है कैप्चा प्रॉक्सी rotation की गाइड.

browser की वाकई कब ज़रूरत पड़ती है, और उसमें छिपा जाल

hrequests किसी response को एक render call से असली browser को सौंप सकता है, और इसकी ख़ूबी यह है कि cookies दोनों दिशाओं में आती-जाती हैं: browser session को उस session की cookies मिल जाती हैं, और page बंद करने पर नई cookies वापस उसमें जुड़ जाती हैं। ऐसे किसी flow के लिए यह वाकई काम का है जिसमें कुछ click करना पड़ता है।

अब वह हिस्सा जिसमें लोगों की पूरी दोपहर चली जाती है। hrequests का Firefox engine Camoufox है, जिसे सीधे Camoufox Python package से launch किया जाता है, और Camoufox page scripts को एक isolated scope में चलाता है। कोई isolated scope DOM पढ़ तो सकता है पर उसे बदल नहीं सकता, इसलिए वह ज़ाहिर-सा तरीक़ा, यानी ऐसा script चलाना जो token को response textarea में लिख दे, चुपचाप कुछ भी नहीं करता। hrequests एक सादा evaluate देता है जो एक script और एक argument लेता है, और main world माँगने का कोई रास्ता नहीं देता।

बचने का रास्ता यह है कि hrequests अपने extra keyword arguments सीधे Camoufox को भेज देता है, इसलिए Camoufox का अपना switch आपके लिए उपलब्ध रहता है। launch पर main world evaluation चालू करें, फिर script के आगे prefix लगाएँ।

import hrequests

# The kwargs go through to Camoufox. Without main_world_eval the
# write below is discarded and nothing tells you.
page = hrequests.BrowserSession(headless=True, main_world_eval=True)
page.goto(SITE)

SCRIPT = (
    "mw:(t) => { "
    "document.getElementById('g-recaptcha-response').value = t; }"
)

# The second argument arrives as t inside the function.
page.evaluate(SCRIPT, token)

page.click("#submit")
page.close()   # merges cookies back into the session

पूरे सवाल से बचने के दो तरीक़े। Chrome engine इस्तेमाल करें, जो सामान्य Playwright semantics है, इसकी क़ीमत उस fingerprint rotation और human cursor emulation को खोना है जिनके बारे में hrequests कहता है कि वे सिर्फ़ Firefox में मिलते हैं। या वही करें जो Step 3 करता है और कभी inject करें ही नहीं: token को वापस TLS session में ले जाएँ और form ख़ुद post करें। किसी login या search form के लिए यह सरल भी है और तेज़ भी, और यही वजह है कि यह गाइड browser को आख़िर में रखती है। अगर आप hrequests के बजाय सीधे Camoufox चला रहे हैं, तो isolated-scope व्यवहार और उसके बाक़ी नतीजे यहाँ कवर किए गए हैं Camoufox कैप्चा गाइड.

एक साथ कई हल करना

hrequests आपको requests को overlap करने के तीन तरीक़े देता है, और CapSkip solves को overlap करने का एक तरीक़ा देता है। ये आपस में जुड़ते तो हैं, पर एक ही चीज़ नहीं हैं।

आप क्या overlap करना चाहते हैंयह काम कौन-सा tool करता है
मुट्ठी भर page fetches, जिन्हें छोड़कर बाद में पढ़ा जाएnohup को true पर सेट करके पास करें, फिर ज़रूरत पड़ने पर एक attribute पढ़ें
एक ही call में URLs की एक सूचीसूची सीधे request method को सौंप दें
concurrency की सीमा के साथ कई requestsबिना भेजे requests बनाएं, फिर उन्हें एक size limit के साथ map करें
एक साथ कई कैप्चा हलPython SDK का asynchronous client, जो किसी उपनाम के बजाय एक असली implementation है

उस आख़िरी row के बारे में पढ़ना सबसे ज़्यादा फ़ायदेमंद है, क्योंकि Python इकलौता CapSkip SDK है जहाँ async client उसी class का दूसरा नाम होने के बजाय एक अलग implementation है। batching का तरीक़ा यहाँ लिखा गया है Python के साथ समानांतर में कैप्चा हल करने की गाइड। fetch वाले हिस्से के लिए hrequests और किसी मुख्यधारा के async client में से चुनना एक अलग सवाल है, और httpx और aiohttp गाइड इसके फ़ायदे-नुक़सान सामने रखती है।

आम errors और उनका मतलब

आप जो देखते हैंकारणफिक्स
SDK से NetworkExceptionCapSkip चल नहीं रहा, या इस machine से उस तक पहुँचा नहीं जा सकताइसे चालू करें, या Server mode पर स्विच करके host सेट करें
token लिख तो दिया जाता है पर widget अनसुलझा ही रहता हैCamoufox के isolated scope ने DOM write को हटा दियाmain world evaluation चालू करके launch करें और script के आगे prefix लगाएँ
किसी render call पर MissingLibraryExceptionhrequests को browser extra के बिना इंस्टॉल किया गया थाextra इंस्टॉल करें, फिर library का install command चलाएँ
एक सही token को site अस्वीकार कर देती हैpost किसी दूसरे session या client से गया थाउसी session के ज़रिए post करें जिसने page लाया था
लंबे अंतराल के बाद एक सही token अस्वीकार हो जाता हैsubmit होने से पहले ही यह expire हो गयाहल और submit एक के बाद एक करें, बीच में कुछ भी नहीं
response में ERROR_GOOGLEKEYpage से निकाला गया sitekey वह नहीं है जो widget में हैकिसी script tag के बजाय data-sitekey attribute पढ़ें
300 सेकंड बाद TimeoutExceptionsitekey और page URL उस widget वाली जोड़ी नहीं हैं, इसलिए हल 300 सेकंड की अधिकतम सीमा तक चलता रहता हैजाँचें कि sitekey और page URL वही जोड़ी हैं जिसे widget असल में इस्तेमाल करता है
browser session कभी छूटता ही नहींcontext manager के बिना बनाया गया कोई page बंद नहीं किया गयाwith वाला रूप इस्तेमाल करें, या किसी finally block में close call करें

FAQ

क्या hrequests ख़ुद कैप्चा हल करता है?

नहीं। यह browser TLS fingerprints की नक़ल करता है और उनसे मेल खाते headers बनाता है, जिससे किसी challenge के बनने से पहले ही बहुत से blocks रुक जाते हैं, और यह किसी rendered page में इंसानी mouse movement तथा typing की नक़ल कर सकता है। इनमें से कुछ भी किसी विकृत तस्वीर को नहीं पढ़ता और न ही कोई reCAPTCHA token बनाता है। वे अलग समस्याएँ हैं और उनके लिए एक सॉल्वर चाहिए।

क्या मुझे browser extra की ज़रूरत है भी?

सिर्फ़ तब जब आपको render करना पड़े। extra पूरा browser stack ले आता है और उसके बाद एक अलग install command माँगता है, और यह एक बड़ा download है। आम flow के लिए, यानी page लाना, sitekey पढ़ना, हल करना, form post करना, सादा install ही काफ़ी है और पूरा काम HTTP requests की तरह चलता है। extra तब जोड़ें जब widget वाकई परोसे गए markup में न हो, या जब form सिर्फ़ असली clicks से ही submit होता हो।

session को किस browser का होने का दावा करना चाहिए?

जिसका भी नाम आप साफ़-साफ़ लिखें। hrequests firefox या chrome स्वीकार करता है और उनसे मेल खाते headers बनाता है, और यह जानबूझकर header version को TLS version के साथ नहीं मिलाता, इस आधार पर कि detection systems इन दोनों को बहुत कम जोड़कर देखते हैं और यह अतिरिक्त फैलाव ज़्यादा clients जैसा लगता है। rendering के लिए library Firefox की सलाह देती है, क्योंकि वहाँ Chrome न fingerprint rotation सपोर्ट करता है और न human cursor emulation।

क्या सॉल्वर स्क्रैपर से अलग किसी machine पर चल सकता है?

हाँ, और स्क्रैपिंग किसी laptop से आगे बढ़ जाने के बाद यही सामान्य setup है। CapSkip को Server mode में रखें ताकि वह loopback address के बजाय आपके network address या किसी public IP पर सुने, फिर host argument को उसी पर लगाएँ। जब caller आपके network के बाहर हो तो एक static public IP की सलाह दी जाती है। हल वही Windows machine वैसे ही बिना मीटर के करती है; सिर्फ़ address बदलता है।

संक्षेप में

किसी named session से fetch करें ताकि fingerprint और cookies स्थिर रहें। built in parser से response में से sitekey पढ़ें। इसे एक ही SDK call से हल करें। token को उसी session के ज़रिए तुरंत वापस post करें, और किसी rendered browser की ओर सिर्फ़ तब बढ़ें जब widget markup में न हो। अगर आप render करते ही हैं, तो याद रखें कि Firefox engine Camoufox है और किसी isolated scope से किया गया DOM write बिना किसी error के ग़ायब हो जाता है, इसलिए या तो main world evaluation चालू करें या injection पूरी तरह छोड़ दें।

अक्सर challenges से टकराने वाले किसी स्क्रैपर को बड़ा करने से पहले एक बात जानने लायक़ है: CapSkip कैप्चा बायपास उस hardware पर करता है जो पहले से आपका है, और आपसे कभी प्रति-हल शुल्क नहीं लेता, इसलिए दस challenges से टकराने वाले run और दस हज़ार से टकराने वाले run, दोनों की लागत बिल्कुल बराबर होती है।