Scarnox · Blog

कैप्चा के बाद खोज परिणाम कैसे स्क्रैप करें (Python गाइड, 2026)

खोज परिणाम पेज उन पहली जगहों में से हैं जहां स्क्रैपर को कैप्चा मिलता है। साइट एक पते से रिक्वेस्ट की बाढ़ देखती है, चैलेंज पेश करती है, और जब तक चैलेंज पास न हो, कोई परिणाम नहीं लौटाती। खोज परिणाम कैप्चा के पार स्क्रैप करने के लिए आपकी स्क्रिप्ट को तीन चरण चाहिए: पार्स करने से पहले चैलेंज पहचानना, एक API कॉल से उसे हल करना, और टोकन सबमिट करना ताकि साइट असली परिणाम पेज लौटाए।

यह गाइड requests और BeautifulSoup के साथ Python में वही फ़्लो दिखाती है। यह उन पेजों को कवर करती है जिन पर PopularCaptcha विजेट दिखता है, वह टाइप जिसे Scarnox आज हल करता है (proxyless)। पहले उस पेज पर कोड चलाने के लिए मुफ्त ट्रायल क्रेडिट के साथ शुरू करें, कार्ड की ज़रूरत नहीं जो आपका है।

चैलेंज कैसा दिखता है

खोज पेज आम तौर पर विजेट को एक फॉर्म के अंदर रखते हैं। विजेट कंटेनर में data-sitekey एट्रिब्यूट होता है, और फॉर्म साइट पर वापस POST करता है:

<form action="/search/verify" method="post">
  <input type="hidden" name="q" value="web scraping">
  <input type="hidden" name="lang" value="en">
  <div class="h-captcha" data-sitekey="YOUR-SITEKEY-UUID"></div>
  <button type="submit">Continue</button>
</form>

आपके कोड को इस मार्कअप से तीन चीज़ें चाहिए: sitekey, फॉर्म का action URL, और वे छिपे फ़ील्ड जो टोकन के साथ वापस भेजने होते हैं। नीचे का हेल्पर तीनों पढ़ता है, इसलिए इन्हें हार्ड-कोड करने की ज़रूरत नहीं।

अगर आपके टार्गेट पर विजेट कोई दूसरा कैप्चा टाइप है, तो कैप्चा के प्रकार देखें। reCAPTCHA और Cloudflare Turnstile सपोर्ट जल्द आ रहा है, इसलिए यहां का कोड केवल PopularCaptcha को कवर करता है।

सॉल्वर कॉल

सॉल्व रिक्वेस्ट Bearer हेडर में आपकी key के साथ Scarnox API पर जाती है। कॉल तब तक रुकती है जब तक टोकन तैयार न हो, इसलिए कोई polling लूप नहीं है:

import time
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

API_KEY = "scarnox_YOURAPIKEY"
SEARCH_URL = "https://search.example.com/search"

session = requests.Session()
session.headers["User-Agent"] = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36"
)


def solve(sitekey: str, page_url: str) -> str:
    r = requests.post(
        "https://api.scarnox.com/api/tasks/create",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "captcha_type": "PopularCaptchaTaskProxyless",
            "site_key": sitekey,
            "site_url": page_url,
        },
        timeout=185,  # टोकन तैयार होने पर कॉल लौटती है
    )
    data = r.json()
    if data.get("errorId") != 0:
        raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
    return data["solution"]["token"]

विफल सॉल्व errorId को 0 से अलग लौटाता है, और उसका शुल्क नहीं लगता। रिट्राई के बारे में कैप्चा सॉल्वर एरर हैंडलिंग में बताया गया है।

पेज लाएं और कैप्चा पास करें

फ़ेच फ़ंक्शन पहले विजेट की जांच करता है। अगर वह नहीं है, तो HTML जैसा है वैसा लौटा देता है। अगर है, तो चैलेंज हल करता है, उसी छिपे फ़ील्ड के साथ फॉर्म दोबारा बनाता है, और उसे POST करता है:

def fetch_results(query: str, page: int = 1) -> str:
    resp = session.get(SEARCH_URL, params={"q": query, "page": page}, timeout=30)
    soup = BeautifulSoup(resp.text, "html.parser")

    widget = soup.select_one("[data-sitekey]")
    if widget is None:
        return resp.text  # इस पेज पर कोई चैलेंज नहीं

    form = widget.find_parent("form")
    if form is None:
        raise RuntimeError("Captcha widget is not inside a form")

    token = solve(widget["data-sitekey"], resp.url)

    payload = {
        field["name"]: field.get("value", "")
        for field in form.select("input[name]")
    }
    payload["h-captcha-response"] = token
    payload["g-recaptcha-response"] = token

    action = urljoin(resp.url, form.get("action") or resp.url)
    verified = session.post(action, data=payload, timeout=30)

    if "data-sitekey" in verified.text:
        raise RuntimeError("Challenge still shown after submit; token may be rejected")
    return verified.text

यहां दो बातें मायने रखती हैं। site_url वह URL है जिस पर कैप्चा असल में दिया गया है (resp.url, जिसमें कोई भी रीडायरेक्ट शामिल है), न कि सादा खोज endpoint। और सेशन GET और POST के बीच कुकीज़ रखता है, जिन्हें कई साइटें टोकन स्वीकार करने के लिए चाहती हैं।

टोकन लगभग दो मिनट में समाप्त हो जाते हैं, इसीलिए सॉल्व फॉर्म पढ़ने के ठीक बाद होता है, पहले नहीं। उस विंडो के बारे में अधिक जानकारी के लिए कैप्चा टोकन की समाप्ति देखें।

परिणाम पार्स करें

जब असली परिणाम पेज लौट आए, तो पार्सिंग सामान्य HTML का काम है। नीचे के selectors प्लेसहोल्डर हैं; पेज को DevTools में खोलें और उन्हें असली selectors से बदलें:

def parse_results(html: str) -> list[dict]:
    soup = BeautifulSoup(html, "html.parser")
    rows = []
    for item in soup.select("div.result"):
        link = item.select_one("a[href]")
        heading = item.select_one("h3")
        if link and heading:
            rows.append({
                "title": heading.get_text(strip=True),
                "url": link["href"],
            })
    return rows


if __name__ == "__main__":
    for page in range(1, 4):
        html = fetch_results("web scraping", page)
        for row in parse_results(html):
            print(row)
        time.sleep(5)  # पेजों के बीच रिक्वेस्ट की गति तय रखें

हर पेज का आउटपुट अलग रखें। अगर कोई पेज शून्य पंक्तियां लौटाए, तो यह मानने से पहले कि क्वेरी का कोई परिणाम नहीं था, विजेट की जांच करें।

ज़िम्मेदारी से स्क्रैप करें

कैप्चा एक संकेत है, कोई खामी नहीं। इस स्क्रिप्ट को किसी भी खोज साइट पर चलाने से पहले:

कानूनी पहलू के लिए क्या वेब स्क्रैपिंग कानूनी है देखें। ब्लॉक से बचने के लिए बिना ब्लॉक हुए स्क्रैप करें पढ़ें।

कीमत

Scarnox हर सफल सॉल्व पर शुल्क लेता है, और विफल सॉल्व मुफ्त हैं। दरों के लिए मौजूदा कीमतें देखें। मुफ्त ट्रायल क्रेडिट के साथ शुरू करें, कार्ड की ज़रूरत नहीं।

अगले कदम