SeleniumBase Tests में कैप्चा कैसे हल करें (Python)

seleniumbase captcha - How to Solve CAPTCHA in SeleniumBase Tests (Python)

SeleniumBase browser चलाता है। यह आपके लिए कैप्चा कभी नहीं पढ़ता। इसलिए SeleniumBase में कैप्चा वाला step तीन चालों का होता है: page से sitekey निकालें, किसी सॉल्वर से token माँगें, फिर उस token को वापस form में लिखकर submit कर दें। हल browser के बाहर होता है, और इसी वजह से वही code किसी headed run, किसी headless run और किसी CI job में एक जैसा काम करता है। यहाँ यह उन दोनों syntax formats में दिया गया है जिनका आप सबसे ज़्यादा इस्तेमाल कर रहे होंगे।

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

  • Python 3.10 या उससे नया, और उसमें SeleniumBase तथा CapSkip SDK इंस्टॉल किए हुए।
  • ऐसा page जो सचमुच कोई widget render करता हो। Google के अपने reCAPTCHA test keys हमेशा पास हो जाते हैं, इसलिए वे आपके code के बारे में कुछ भी साबित नहीं करते।
  • CapSkip चालू हो, या तो loopback पते पर Local mode में या ऐसी मशीन पर Server mode में जहाँ तक आपका test runner पहुँच सके। दोनों यहाँ बताए गए हैं: कनेक्शन सेटिंग्स। और आपको कौन सा चाहिए, यह इस पर निर्भर करता है कि आपके tests कहाँ चलते हैं।
# Both packages, one command.
pip install seleniumbase capskip

UC mode क्या करता है, और क्या नहीं करता

SeleniumBase के साथ UC mode आता है, और इसके काम के बारे में सटीक होना ज़रूरी है क्योंकि लोग इसे सॉल्वर समझकर उठा लेते हैं। UC mode उन automation signals को कम करता है जो कोई browser बाहर छोड़ता है, और इसके GUI helpers किसी Cloudflare interstitial पर checkbox क्लिक कर सकते हैं। यह reCAPTCHA token बनाने से अलग समस्या है। UC mode में ऐसा कुछ नहीं है जो किसी बिगड़े हुए image को पढ़े या उन tiles को चुने जिनमें bus है।

# pip install seleniumbase
from seleniumbase import SB

with SB(uc=True) as sb:
    # Disconnects the driver briefly so the page loads unobserved.
    sb.uc_open_with_reconnect("https://example.com/protected", reconnect_time=3)

    # Drives the real mouse pointer, so it needs a desktop session
    # or a virtual display. It clicks a checkbox; it solves nothing.
    sb.uc_gui_click_captcha()

इससे दो नतीजे निकलते हैं। GUI helpers को एक असली display चाहिए, जो उन्हें ज़्यादातर headless CI से बाहर कर देता है। और reCAPTCHA तथा GeeTest के लिए आपको फिर भी एक token चाहिए, और यही बाक़ी पोस्ट का विषय है। दोनों को साथ इस्तेमाल करें: UC mode इसलिए कि आपको कम बार challenge मिले, और सॉल्वर उन challenges के लिए जो फिर भी आ जाते हैं।

Step 1: page से sitekey पढ़ें

sitekey सार्वजनिक होता है। यह widget element पर एक attribute के रूप में बैठा रहता है, और SeleniumBase इसे एक ही call में पढ़ लेता है, इसलिए आपको इसे हर environment के लिए hardcode करने की ज़रूरत कभी नहीं पड़ती।

# pip install seleniumbase
from seleniumbase import SB

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

with SB() as sb:
    sb.open(PAGE)

    # Present on the widget div for v2, and on the script tag for v3.
    sitekey = sb.get_attribute("[data-sitekey]", "data-sitekey")

    print(sitekey)      # this plus the page URL is all the solver needs

Step 2: सॉल्वर से token लें

इस हिस्से का SeleniumBase से कोई लेना-देना नहीं है। यह आपकी अपनी मशीन पर चल रही किसी service को किया गया एक सामान्य Python call है, और यह वही token string लौटाता है जो page ने तब बनाई होती अगर कोई इंसान widget पार कर गया होता।

# pip install capskip
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

# v2 checkbox is the default shape. Pass invisible=1 or
# enterprise=1 for those variants, or version="v3" for v3.
result = solver.recaptcha(
    sitekey=sitekey,
    url=PAGE,
)

token = result["code"]      # the value the form is waiting for

वही client उन बाक़ी प्रकारों को भी संभालता है जिनसे किसी test suite में आपका सामना होने की संभावना है। Turnstile के लिए sitekey और page URL के साथ solver.turnstile है, GeeTest के लिए gt और challenge values के साथ solver.geetest है, और image कैप्चा के लिए किसी file path, किसी URL या किसी base64 data URI के साथ solver.normal है। Python कैप्चा सॉल्वर पेज पूरा दायरा कवर करता है।

Step 3: token inject करें और submit करें

Google form में एक hidden textarea रखता है और उसकी value में token की अपेक्षा करता है। उसमें एक script call से लिखें, फिर form को उसी तरह submit करें जैसे page का अपना UI करता।

# The response field is hidden, so a normal type() will not reach it.
sb.execute_script(
    "document.getElementById('g-recaptcha-response').value = arguments[0];",
    token,
)

sb.click("button[type='submit']")
sb.assert_element(".signup-success")

अगर page submit के समय field पढ़ने के बजाय widget से अपना ही callback function जोड़ता है, तो क्लिक करने के बजाय उस function को token के साथ call करें। आपको कौन सा चाहिए, यह widget markup में दिख जाता है: data-callback attribute उस function का नाम बताता है, और उसका न होना मतलब form field ही पढ़ता है।

पूरा test

यहाँ पूरी चीज़ एक BaseCase class के रूप में है, और यही वह format है जो किसी मौजूदा pytest suite में बिना किसी अतिरिक्त जोड़-तोड़ के फिट हो जाता है।

# pip install seleniumbase capskip
from seleniumbase import BaseCase
from capskip import CapSkip

BaseCase.main(__name__, __file__)

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


class RecaptchaTest(BaseCase):
    def test_signup_form(self):
        self.open(PAGE)
        sitekey = self.get_attribute("[data-sitekey]", "data-sitekey")

        solver = CapSkip(host="127.0.0.1", port=8080)
        token = solver.recaptcha(sitekey=sitekey, url=PAGE)["code"]

        self.execute_script(
            "document.getElementById('g-recaptcha-response').value = arguments[0];",
            token,
        )
        self.click("button[type='submit']")
        self.assert_element(".signup-success")

देर से हल करें। कोई reCAPTCHA token लगभग दो मिनट तक चलता है, इसलिए किसी test की शुरुआत में एक token लाकर उसे चार और steps के बाद इस्तेमाल करना ऐसी दौड़ है जिसे आप बीच-बीच में हारते रहेंगे। हल को ठीक submit से पहले रखें, और retry की जगह भी वही है।

सॉल्वर को किसी server पर चलाना

test runners शायद ही कभी वही मशीन होते हैं जिस पर आप बैठे होते हैं। CapSkip इसे एक दूसरे connection mode से संभालता है, और आपके code में बदलती है सिर्फ़ host की value।

मोडकिस पर सुनता हैकब इस्तेमाल करें
लोकल127.0.0.1, केवल उसी डिवाइस परTests और सॉल्वर एक ही मशीन पर चलते हैं
सर्वरआपका नेटवर्क पता या पब्लिक IPकोई CI runner, कोई VPS या कोई test grid बाहर से call करता है
# pip install capskip
import os
from capskip import CapSkip

# The SDK reads these names from the environment too, so one test
# file runs unchanged on a laptop and on a shared runner.
solver = CapSkip(
    host=os.environ.get("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.environ.get("CAPSKIP_PORT", "8080")),
)

जब call करने वाले आपके अपने network के बाहर बैठे हों तो एक static public IP रखने की सलाह दी जाती है। Server mode अब भी आपका अपना hardware है और अब भी unmetered है: यह बदलता है कि सॉल्वर कहाँ चलता है, कभी यह नहीं कि उसका मालिक कौन है या प्रति हल उसकी लागत क्या है। विकल्पों का पूरा सेट यहाँ मिलता है: कनेक्शन सेटिंग्स.

आम errors

आप जो देखते हैंकारणफिक्स
NetworkExceptionउस host और port पर कोई नहीं सुन रहाCapSkip शुरू करें, या host को उस server की ओर मोड़ें जिस पर वह चल रहा है
TimeoutExceptionPolling recaptchaTimeout से आगे निकल गईtimeout बढ़ाएँ, या जाँचें कि sitekey वही live वाला है
ERROR_GOOGLEKEYsitekey आया ही नहीं या ख़राब हैभेजने से पहले print करें कि get_attribute ने क्या लौटाया
ERROR_PAGEURLpage URL नदारद है या पूरा URL नहीं हैवही absolute URL भेजें जिस पर browser है
Form एक वैध token को अस्वीकार करता हैpage field के बजाय किसी callback का इस्तेमाल करता हैdata-callback वाले function को token के साथ call करें

API जो भी code लौटा सकता है, वे सब CapSkip API डॉक्यूमेंटेशन में दिए गए हैं, साथ में यह भी कि हर एक किससे ट्रिगर होता है।

FAQ

क्या UC mode अपने आप reCAPTCHA हल कर देता है?

नहीं। UC mode browser को कम automated दिखाता है और GUI helpers के ज़रिए किसी Cloudflare interstitial पर checkbox क्लिक कर सकता है। इनमें से कोई भी reCAPTCHA token नहीं बनाता। token आप फिर भी किसी सॉल्वर से लाते हैं और उसे form में लिखते हैं, ठीक वैसे ही जैसे ऊपर दिखाया गया है। दोनों चलाएँ: UC mode यह घटाता है कि आपको कितनी बार challenge मिले, और सॉल्वर उन challenges को पार करा देता है जो आपको मिल जाते हैं।

क्या मैं इसे CI में headless चला सकता हूँ?

हाँ, क्योंकि हल कभी browser को छूता ही नहीं। SB को headless पास करें या pytest की command line पर flag जोड़ दें, तीनों steps वैसे के वैसे रहते हैं। किसी headless runner पर जो हिस्सा नहीं टिकता वह है UC mode की GUI clicking, जो एक असली mouse pointer चलाती है और जिसे कोई desktop session या कोई virtual display चाहिए।

मेरे tests किसी Linux runner पर चलते हैं। सॉल्वर कहाँ जाएगा?

अपने नियंत्रण वाली किसी Windows मशीन पर, जहाँ तक Server mode में पहुँचा जाता है। CapSkip एक Windows application है, इसलिए तरीक़ा यह है कि एक Windows मशीन पर सॉल्वर का एक instance रहे और जितने चाहें उतने runners API के ज़रिए उसी की ओर इशारा करें। runner पर CAPSKIP_HOST सेट कर दें, test में और कुछ नहीं बदलता।

क्या हल को मेरे browser से मेल खाने के लिए किसी प्रॉक्सी की ज़रूरत है?

कभी-कभी, और reCAPTCHA, Turnstile तथा GeeTest के लिए यह समर्थित है। एक type और एक URI वाली proxy dictionary पास करें और हल उसी के ज़रिए किया जाता है, जो तब मायने रखता है जब site को इसकी परवाह हो कि token और session एक ही पते से आएँ। Image कैप्चा कोई प्रॉक्सी नहीं लेते, क्योंकि उनका कुछ भी किसी network path से बँधा नहीं होता।

संक्षेप में

get_attribute से sitekey पढ़ें, token लाएँ, उसे hidden response field में लिखें, submit करें। हल को submit वाले उसी step में रखें ताकि token ताज़ा रहे, और host को किसी environment variable में रखें ताकि suite हर जगह एक जैसी चले। व्यापक Selenium तस्वीर के लिए देखें: Selenium कैप्चा सॉल्वर पेज, और v2 की बारीकियों के लिए देखें: reCAPTCHA v2 सॉल्वर पेज। इसके बाद बचती है लागत, और यही वह जगह है जहाँ हर commit पर चलने वाली suite सबसे ज़्यादा चुभती है: लोकल captcha सॉल्वर का मतलब है कि हर हल उसी hardware पर होता है जो पहले से आपका अपना है, बिना मीटर के, चाहे tests कितनी भी बार चलें।