In this Article

scrape google shopping

In this Article

گوگل شاپنگ کی اسکریپنگ کا مطلب ہے گوگل کے شاپنگ نتائج سے بڑے پیمانے پر منظم پروڈکٹ ڈیٹا، مثلا عنوانات، قیمتیں، فروخت کنندگان، ریٹنگز اور شپنگ نوٹس، اکٹھا کرنا۔ چونکہ یہ نتائج سخت حفاظتی نظام کے پیچھے ہوتے ہیں اور مقام کے مطابق بدلتے ہیں، اس لیے قابل اعتماد اسکریپنگ کے لیے گھومتی ہوئی IPs اور درست جیو ٹارگٹنگ چاہیے، صرف ایک کنکشن پر چلتا ہوا اسکریپر کافی نہیں ہوتا۔

یہ گائیڈ کوڈ پر مرکوز ہے۔ اس میں جیو ٹارگیٹڈ درخواستیں، ملک کے حساب سے پراکسیز کے ذریعے روٹنگ، گوگل کے جان بوجھ کر مبہم بنائے گئے پروڈکٹ کارڈز کی پارسنگ، صفحہ بندی، ریٹ لمٹس پر دوبارہ کوشش اور بیک آف، رضامندی کے ڈائیلاگ سے نمٹنے والا ہیڈ لیس براؤزر متبادل، CSV ایکسپورٹ کے ساتھ صاف ڈیٹا ماڈل، قیمتوں کی تاریخ کا ٹریکر، اور مانیٹرنگ شیڈول شامل ہیں۔ یہ اینٹی باٹ حقیقت، اپنے بنائے ہوئے اسکریپر اور ادا شدہ SERP API کے درمیان سمجھوتوں، اور قانونی حدود کو بھی صاف لفظوں میں بیان کرتی ہے۔

DataImpulse ایک اخلاقی پراکسی فراہم کنندہ ہے جو 195 ممالک میں 90 ملین سے زیادہ رہائشی، موبائل اور ڈیٹا سینٹر IP ایڈریسز دیتا ہے۔ اس کا پے-ایز-یو-گو ماڈل فی جی بی 1 ڈالر سے شروع ہوتا ہے، ٹریفک کی میعاد ختم نہیں ہوتی، اور اسے ویب اسکریپنگ، اشتہار کی تصدیق، قیمتوں کی نگرانی، مارکیٹ ریسرچ اور ملٹی اکاؤنٹ مینجمنٹ کے لیے استعمال کیا جاتا ہے۔

اہم حقائق

  • مقامی قیمتیں: گوگل شاپنگ کو درست طریقے سے اسکریپ کرنے کے لیے gl اور hl پیرامیٹرز سیٹ کریں اور درخواستوں کو ہدف ملک کی IP کے ذریعے روٹ کریں، کیونکہ قیمتیں، فروخت کنندگان اور دستیابی خطے کے لحاظ سے بدلتے ہیں۔
  • بہترین پراکسی کی قسم: گھومتی ہوئی رہائشی پراکسیز، کیونکہ وہ حقیقی صارف IPs استعمال کرتی ہیں اور پکڑے جانے کا امکان کم ہوتا ہے۔
  • قیمت: فی جی بی 1 ڈالر سے شروع، پے-ایز-یو-گو، بغیر میعاد ختم ہونے والی ٹریفک اور بغیر سبسکرپشن کے۔
  • کوریج: 195 ممالک میں اخلاقی طور پر حاصل کردہ 90 ملین سے زیادہ IPs۔
  • بھروسہ: 99.51% کامیابی کی شرح، G2 پر 5 میں سے 4.8 درجہ بندی۔
  • پروٹوکولز اور ٹارگٹنگ: HTTP، HTTPS اور SOCKS5، ملک کی سطح کی ٹارگٹنگ سمیت۔
گوگل شاپنگ کے پروڈکٹ ڈیٹا کو اکٹھا کرنا

آپ گوگل شاپنگ سے کون سا ڈیٹا اسکریپ کر سکتے ہیں؟

گوگل شاپنگ پروڈکٹ لسٹنگز میں کئی منظم فیلڈز دکھاتا ہے جو قیمتوں اور مارکیٹ ریسرچ کے لیے مفید ہوتے ہیں۔ ہر نتیجے میں عموما ایک جیسے اجزا ہوتے ہیں جنہیں نکال کر قطاروں کی شکل میں نارملائز کیا جا سکتا ہے۔

  • پروڈکٹ کی تفصیلات: عنوان، تفصیل کا خلاصہ، برانڈ، ماڈل، اور پروڈکٹ تصویر کا URL۔
  • قیمت: درج شدہ قیمت، کرنسی، اور بعض اوقات بیچنے والوں کے درمیان قیمت کی حد۔
  • فروخت کنندہ: مرچنٹ کا نام اور، پروڈکٹ تفصیل کے صفحے پر، اسی آئٹم کی پیشکش کرنے والے مسابقتی فروخت کنندگان کی فہرست۔
  • ریٹنگز اور جائزے: جہاں دستیاب ہوں، مجموعی اسٹار ریٹنگ اور جائزوں کی تعداد۔
  • دستیابی اور شپنگ: اسٹاک کی حالت اور شپنگ نوٹس، جو خطے کے لحاظ سے بدلتے ہیں۔

گوگل جب بھی اپنا لے آؤٹ بدلتا ہے تو اصل فیلڈز بھی بدل سکتی ہیں، اس لیے پارسر کو غائب ویلیوز اور بدلتے مارک اپ کے ساتھ چلنا چاہیے۔ ہر فیلڈ کو اختیاری سمجھیں اور نکالنے کے بعد ٹائپس کی تصدیق کریں، یہ فرض نہ کریں کہ ریٹنگ یا فروخت کنندہ ہمیشہ موجود ہوگا۔ چونکہ ایک ہی پروڈکٹ مختلف ممالک میں مختلف قیمتوں پر دکھائی دے سکتی ہے، اس لیے اپنا اسکیما شروع ہی سے (پروڈکٹ، ملک، ٹائم اسٹیمپ) والی کلید کے گرد بنائیں، بعد میں جغرافیہ جوڑنے کے بجائے۔

آپ گوگل شاپنگ کو جیو ٹارگیٹڈ درخواست کیسے بھیجتے ہیں؟

جیو ٹارگیٹڈ درخواست بھیجنے کے لیے شاپنگ ٹیب فلیگ اور لوکیل پیرامیٹرز کے ساتھ گوگل کے سرچ اینڈ پوائنٹ کو کال کریں، پھر وہی IP اور پیرامیٹر سگنلز استعمال کریں جو ایک حقیقی خریدار بھیجتا۔ دو اہم پیرامیٹرز gl (ملک، مثلا جرمنی کے لیے gl=de) اور hl (انٹرفیس کی زبان، مثلا hl=de) ہیں۔ تیسرا مفید اشارہ location طرز کی اصطلاح ہے جسے آپ کوئری کے سیاق میں شامل کر سکتے ہیں، لیکن مماثل ایگزٹ IP کے ساتھ gl زیادہ تر کام کر دیتا ہے۔

صرف پیرامیٹرز سیٹ کرنا کافی نہیں، کیونکہ گوگل درخواست کی IP بھی دیکھتا ہے تاکہ طے کر سکے کہ کون سی قیمتیں اور فروخت کنندگان دکھانے ہیں۔ نیچے دی گئی کم سے کم درخواست حقیقت پسندانہ ہیڈرز اور لوکیل کا جوڑا بھیجتی ہے۔ اسے جان بوجھ کر پراکسی کے بغیر رکھا گیا ہے تاکہ IP پرت شامل کرنے سے پہلے بنیادی کال صاف نظر آئے۔

import requests

def build_params(query, country="us", lang="en", start=0):
    return {
        "q": query,
        "tbm": "shop",   # shopping vertical
        "gl": country,    # country bias, e.g. de, gb, fr
        "hl": lang,       # interface language
        "num": 40,        # results per page (soft cap)
        "start": start,   # pagination offset
    }

HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/124.0 Safari/537.36"
    ),
    "Accept-Language": "en-US,en;q=0.9",
}

resp = requests.get(
    "https://www.google.com/search",
    params=build_params("wireless headphones", country="us", lang="en"),
    headers=HEADERS,
    timeout=30,
)
print(resp.status_code, len(resp.text))

Accept-Language ہیڈر کو hl کے ساتھ ہم آہنگ رکھیں۔ انگریزی ہیڈر کے ساتھ جرمن قیمتوں والا صفحہ مانگنا ایک غیر فطری تضاد ہے اور غلط کرنسی بھی واپس آ سکتی ہے۔ اسکیل پر یہی بنیادی فنکشن لوکیل کا واحد فیصلہ کن مقام بن جاتا ہے، اس لیے بعد کی ہر کال یکساں رہتی ہے۔

آپ ملک کے لحاظ سے ٹارگٹڈ پراکسیز کے ذریعے درخواستیں کیسے روٹ کرتے ہیں؟

ملک کے لحاظ سے ٹارگٹڈ پراکسی کے ذریعے روٹ کرنے کے لیے requests کو ایک ہی گیٹ وے کی طرف بھیجیں اور ہدف ملک کو پراکسی یوزرنیم میں شامل کریں۔ DataImpulse کا گیٹ وے gw.dataimpulse.com:823 ہے، اور __cr.us یا __cr.de لگانے سے ایگزٹ ملک منتخب ہوتا ہے۔ ملک کی ٹارگٹنگ بنیادی قیمت میں شامل ہے، جبکہ ریاست، شہر، زپ کوڈ اور ASN ٹارگٹنگ ادا شدہ ایڈ آنز ہیں۔ اگر پراکسی تصدیق آپ کے لیے نئی ہے، تو ہماری گائیڈ پراکسی تصدیق یوزرنیم اور پاس ورڈ کے طریقہ کار کو تفصیل سے سمجھاتی ہے۔

import requests

USER = "your_login"
PASS = "your_password"
GATEWAY = "gw.dataimpulse.com:823"

def proxy_for(country):
    # __cr. pins the exit IP to that country
    cred = f"{USER}__cr.{country}:{PASS}"
    url = f"http://{cred}@{GATEWAY}"
    return {"http": url, "https": url}

resp = requests.get(
    "https://www.google.com/search",
    params=build_params("wireless headphones", country="de", lang="de"),
    headers=HEADERS,
    proxies=proxy_for("de"),
    timeout=30,
)
print(resp.status_code, len(resp.text))

اہم اصول یہ ہے کہ پراکسی ملک اور gl/hl جوڑا ایک ساتھ بدلیں۔ کراس مارکیٹ قیمتوں کا موازنہ بنانے کے لیے ممالک کی فہرست پر لوپ چلائیں، اور ایگزٹ IP اور لوکیل کو ہم آہنگ رکھیں تاکہ ہر جواب ایک ہی مستقل خریدار مقام کی عکاسی کرے۔

MARKETS = [
    {"country": "us", "lang": "en"},
    {"country": "de", "lang": "de"},
    {"country": "gb", "lang": "en"},
    {"country": "fr", "lang": "fr"},
]

def fetch_market(query, market):
    c, lang = market["country"], market["lang"]
    return requests.get(
        "https://www.google.com/search",
        params=build_params(query, country=c, lang=lang),
        headers={**HEADERS, "Accept-Language": f"{lang};q=0.9"},
        proxies=proxy_for(c),
        timeout=30,
    )

for m in MARKETS:
    r = fetch_market("wireless headphones", m)
    print(m["country"], r.status_code, len(r.text))

DataImpulse IP پرت فراہم کرتا ہے، منظم اسکریپنگ سروس نہیں، اس لیے اسکریپر کی ذمہ داری آپ کی ہے۔ گھومتی ہوئی رہائشی پراکسیز یہاں عموما بہترین رہتی ہیں کیونکہ وہ حقیقی صارف ڈیوائسز سے آتی ہیں؛ ڈیٹا سینٹر پراکسیز سستی ہوتی ہیں مگر آسانی سے فلیگ ہو سکتی ہیں، اور موبائل پراکسیز مشکل ترین اہداف کے لیے کیریئر گریڈ IPs دیتی ہیں۔

آپ گوگل شاپنگ کے پروڈکٹ کارڈز کو کیسے پارس کرتے ہیں؟

پروڈکٹ کارڈز کو ایسی HTML لائبریری سے پارس کریں جو خراب یا بدلتے مارک اپ کو برداشت کر سکے، اور نازک گہرے سلیکٹرز کے بجائے مستحکم ٹیکسٹ پیٹرنز پر انحصار کریں، کیونکہ گوگل کے کلاس نام مبہم ہوتے ہیں اور بار بار بدلتے ہیں۔ آج براؤزر کے ڈیو ٹولز سے کاپی کیا گیا سلیکٹر چند ہفتوں میں ٹوٹ سکتا ہے، اس لیے پارسر کو اس طرح بنائیں کہ لے آؤٹ بدلنے پر کریش نہ کرے بلکہ کچھ فیلڈز چھوڑ کر آگے بڑھ جائے۔

ایک مضبوط طریقہ ہر ممکنہ کارڈ کو پڑھتا ہے، ٹیگ اسٹرکچر سے عنوان اور تصویر نکالتا ہے، اور کرنسی کو سمجھنے والی ریگولر ایکسپریشن سے قیمت نکالتا ہے۔ نیچے دیے گئے سلیکٹرز حقیقت پسندانہ مثالیں ہیں، ضمانت نہیں؛ انہیں اپ ڈیٹ کرنا پڑ سکتا ہے، اس لیے ریجیکس کو قابل اعتماد fallback کے طور پر رکھیں۔

from bs4 import BeautifulSoup
import re

# Currency-aware price matcher: symbol optional, thousands and decimals tolerated.
PRICE_RE = re.compile(r"(?:[$€£]|USD|EUR|GBP)\s?\d[\d.,]*")

def parse_cards(html):
    soup = BeautifulSoup(html, "html.parser")
    rows = []
    # These class names ROTATE; treat them as hints, keep the fallbacks.
    candidates = soup.select("div.sh-dgr__content, div.sh-dlr__list-result, div[data-docid]")
    if not candidates:
        candidates = soup.find_all("div")  # last-resort sweep
    for card in candidates:
        text = card.get_text(" ", strip=True)
        price_match = PRICE_RE.search(text)
        if not price_match or len(text) > 400:
            continue
        img = card.find("img")
        link = card.find("a", href=True)
        rows.append({
            "title": _first_text(card, ["h3", "h4"]),
            "price_raw": price_match.group(0),
            "image": img.get("src") if img else None,
            "url": link["href"] if link else None,
        })
    return rows

def _first_text(card, tags):
    for t in tags:
        el = card.find(t)
        if el and el.get_text(strip=True):
            return el.get_text(strip=True)
    return None

CURRENCY = {"$": "USD", "€": "EUR", "£": "GBP"}

def normalize_price(raw):
    if not raw:
        return None, None
    symbol = next((s for s in CURRENCY if s in raw), None)
    code = CURRENCY.get(symbol, "USD")
    digits = re.sub(r"[^\d.,]", "", raw).replace(",", "")
    try:
        return float(digits), code
    except ValueError:
        return None, code

چونکہ مبہم مارک اپ یہاں معمول ہے، کچھ ٹیمیں اس کے بجائے رینڈر شدہ DOM استعمال کرتی ہیں۔ اسٹیٹک HTML اور رینڈر شدہ صفحات کی پارسنگ کے وسیع تر tradeoffs کے لیے ہماری گائیڈ ڈائنامک ویب پیجز کو اسکریپ کرنا دیکھیں۔

جب گوگل 429 واپس کرتا ہے تو آپ پیجینیشن اور بیک آف کیسے کرتے ہیں؟

start آفسیٹ کو اپنے پیج سائز کے مطابق آگے بڑھا کر صفحہ بندی کریں، اور HTTP 429، خالی جوابات یا CAPTCHA کو اس اشارے کے طور پر لیں کہ انتظار کر کے تازہ IP سے دوبارہ کوشش کرنی ہے۔ گوگل بار بار آنے والی خودکار درخواستوں کو سختی سے محدود کرتا ہے، اس لیے صفحہ بندی اور بیک آف ایک ہی لوپ میں ہونے چاہئیں۔

صفحات کو اس وقت تک چلائیں جب تک کوئی درخواست کارڈز واپس نہ کرے یا آپ پیج حد تک نہ پہنچ جائیں۔ پراکسی ڈکشنری دوبارہ بنا کر صفحات کے درمیان ایگزٹ IP گھمائیں، اور صرف اسٹیٹس کوڈ پر بھروسہ کرنے کے بجائے باڈی میں رضامندی یا CAPTCHA کے نشانات دیکھ کر نرم بلاکس پہچانیں۔

BLOCK_MARKERS = ("unusual traffic", "/sorry/", "consent.google", "captcha")

def is_blocked(resp):
    if resp.status_code in (429, 503):
        return True
    body = resp.text.lower()
    return any(m in body for m in BLOCK_MARKERS)

def paginate(query, market, max_pages=5, page_size=40):
    all_rows = []
    for page in range(max_pages):
        params = build_params(query, market["country"], market["lang"],
                              start=page * page_size)
        resp = get_with_retry(
            "https://www.google.com/search",
            params=params, proxies=proxy_for(market["country"]),
        )
        if resp is None:
            break
        rows = parse_cards(resp.text)
        if not rows:
            break  # no more results
        all_rows.extend(rows)
    return all_rows

نیچے دیا گیا دوبارہ کوشش کرنے والا ہیلپر جٹر کے ساتھ ایکسپونینشل بیک آف استعمال کرتا ہے، جس سے کوششیں پھیل جاتی ہیں اور بلاک شدہ ورکرز ایک ہی لمحے میں دوبارہ نہیں ٹوٹ پڑتے۔ ہر کوشش پراکسی ڈکشنری دوبارہ لیتی ہے، اس لیے گھومتا ہوا پول اگلی کوشش میں نئی IP دے سکتا ہے۔

import time, random

def get_with_retry(url, params, proxies, max_attempts=4):
    for attempt in range(max_attempts):
        try:
            resp = requests.get(url, params=params, headers=HEADERS,
                                proxies=proxies, timeout=30)
        except requests.RequestException:
            resp = None
        if resp is not None and not is_blocked(resp):
            return resp
        # exponential backoff: 2, 4, 8 seconds, plus jitter
        wait = (2 ** (attempt + 1)) + random.uniform(0, 1.5)
        time.sleep(wait)
    return None  # exhausted; caller decides what to do

دوبارہ کوششیں کامیاب ہو رہی ہوں تب بھی درخواستوں کی رفتار معقول رکھیں۔ صفحات کے درمیان مناسب بنیادی تاخیر، IP گردش کے ساتھ مل کر، طویل مدت میں تیز رفتاری سے درخواستیں بھیجنے اور پھر ری ٹرائیز پر انحصار کرنے سے کہیں بہتر ہے۔ ویب اسکریپنگ کے بہترین طریقوں پر ہمارے نوٹس رفتار اور ہیڈر hygiene کو مزید تفصیل سے سمجھاتے ہیں۔

آپ ہیڈ لیس براؤزر کے ساتھ بلاک شدہ صفحات کو کیسے رینڈر کرتے ہیں؟

جب عام HTTP درخواست بار بار رضامندی کی دیواروں یا JavaScript سے رینڈر ہونے والے مواد پر اٹک جائے، تو ہیڈ لیس براؤزر استعمال کریں جو صفحے کو حقیقی کلائنٹ کی طرح چلائے اور DOM پڑھنے سے پہلے رضامندی ڈائیلاگ بند کرے۔ Playwright اس کام کے لیے موزوں ہے کیونکہ یہ ہر context کے لیے پراکسیز اور قابل اعتماد waits کو سپورٹ کرتا ہے۔

نیچے دیا گیا اسکرپٹ ملک کے لحاظ سے ٹارگٹڈ DataImpulse پراکسی کے ذریعے Chromium چلاتا ہے، وہ کوکی یا رضامندی ڈائیلاگ سنبھالتا ہے جو یورپی لوکیلز میں عموما دکھتا ہے، مواد کا انتظار کرتا ہے، اور رینڈر شدہ HTML واپس کرتا ہے تاکہ آپ اسے اسی parse_cards فنکشن میں دے سکیں۔

from playwright.sync_api import sync_playwright

def render_shopping(query, country="de", lang="de"):
    cred_user = f"{USER}__cr.{country}"
    params = f"?q={query.replace(' ', '+')}&tbm=shop&gl={country}&hl={lang}"
    url = "https://www.google.com/search" + params
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context(
            proxy={
                "server": "http://gw.dataimpulse.com:823",
                "username": cred_user,
                "password": PASS,
            },
            locale=f"{lang}-{country.upper()}",
            user_agent=HEADERS["User-Agent"],
        )
        page = context.new_page()
        page.goto(url, wait_until="domcontentloaded", timeout=45000)
        _dismiss_consent(page)
        page.wait_for_timeout(2000)
        html = page.content()
        browser.close()
        return html

def _dismiss_consent(page):
    # Consent dialogs vary by locale; try a few common accept buttons.
    for label in ("Accept all", "Alle akzeptieren", "Tout accepter",
                  "I agree", "Accept"):
        try:
            btn = page.get_by_role("button", name=label)
            if btn.count() > 0:
                btn.first.click(timeout=3000)
                page.wait_for_timeout(1000)
                return
        except Exception:
            continue

ہیڈ لیس براؤزر خام درخواست کے مقابلے میں CPU اور میموری زیادہ لیتا ہے، اس لیے اسے ڈیفالٹ راستہ بنانے کے بجائے صرف ان صفحات کے لیے استعمال کریں جنہیں واقعی رینڈرنگ چاہیے۔ بہت سی ٹیمیں رفتار کے لیے براہ راست HTTP چلاتی ہیں اور صرف اس وقت Playwright پر جاتی ہیں جب is_blocked بار بار فعال ہو۔ اگر آپ کا اسٹیک Python کے بجائے JavaScript ہے، تو یہی پیٹرن Puppeteer کے ساتھ بھی چلتا ہے؛ JavaScript کے ساتھ ویب اسکریپنگ دیکھیں۔

آپ اسکریپ شدہ ڈیٹا کو کیسے ترتیب دیتے اور ایکسپورٹ کرتے ہیں؟

ڈیٹا کو ایک مستحکم ریکارڈ کے گرد ترتیب دیں جس میں مارکیٹ اور کیپچر ٹائم اسٹیمپ ہمیشہ شامل ہوں، پھر CSV میں ایکسپورٹ کریں تاکہ آؤٹ پٹ کا موازنہ، اسپریڈ شیٹ میں لوڈنگ، یا ویئر ہاؤس میں بھیجنا آسان ہو۔ ایک dataclass ٹائپ ہنٹس اور ہر قطار کی واضح تعریف دیتا ہے۔

from dataclasses import dataclass, asdict, field
from datetime import datetime, timezone
import csv

@dataclass
class Offer:
    query: str
    country: str
    title: str | None
    price: float | None
    currency: str | None
    seller: str | None = None
    url: str | None = None
    captured_at: str = field(
        default_factory=lambda: datetime.now(timezone.utc).isoformat()
    )

def to_offers(rows, query, country):
    offers = []
    for r in rows:
        price, currency = normalize_price(r.get("price_raw"))
        offers.append(Offer(
            query=query, country=country, title=r.get("title"),
            price=price, currency=currency, url=r.get("url"),
        ))
    return offers

اس کے بعد CSV لکھنا صرف dataclass فیلڈز ڈمپ کرنے کا کام رہ جاتا ہے۔ اپینڈ موڈ اور ہیڈر گارڈ شیڈول شدہ جاب کو فائل دوبارہ لکھے بغیر وقت کے ساتھ بڑھاتے رہتے ہیں۔

import os

def export_csv(offers, path="google_shopping.csv"):
    if not offers:
        return
    fieldnames = list(asdict(offers[0]).keys())
    write_header = not os.path.exists(path)
    with open(path, "a", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        if write_header:
            writer.writeheader()
        for o in offers:
            writer.writerow(asdict(o))

ہر قطار میں ملک اور ٹائم اسٹیمپ رکھنے سے بعد میں آپ ایسے سوالات کے جواب دے سکتے ہیں کہ آج کسی SKU کے لیے کون سی مارکیٹ سب سے سستی ہے، یا اس ہفتے قیمت کیسے بدلی۔ جغرافیہ اور وقت والی یہی کلید اگلے سیکشن کے قیمت تاریخ ٹریکر کی بنیاد بنتی ہے۔

آپ وقت کے ساتھ گوگل شاپنگ کی قیمت کی تاریخ کو کیسے ٹریک کرتے ہیں؟

قیمتوں کی تاریخ ٹریک کرنے کے لیے ہر observation کو ایک چھوٹے ڈیٹا بیس میں پروڈکٹ، ملک اور دن کی کلید پر اپسرٹ کریں، تاکہ اسکریپر دوبارہ چلانے سے آج کی قطار نقل نہ ہو بلکہ اپ ڈیٹ ہو، جبکہ پچھلے دن محفوظ رہیں۔ SQLite لاکھوں قطاروں کے لیے کافی ہے اور اسے سرور نہیں چاہیے، اس لیے مانیٹرنگ جاب خود کفیل رہتا ہے۔

نیچے دیا گیا اسکیما ایک مرکب منفرد کلید اور ON CONFLICT upsert استعمال کرتا ہے۔ ایک ہی دن اسکریپر دو بار چلانے سے اس (پروڈکٹ، ملک، دن) کے لیے تازہ ترین قیمت اوور رائٹ ہو جاتی ہے؛ کئی دن تک چلانے سے وہ ٹائم سیریز بنتی ہے جسے آپ بعد میں چارٹ کر سکتے ہیں۔

import sqlite3

DDL = """
CREATE TABLE IF NOT EXISTS price_history (
    product   TEXT NOT NULL,
    country   TEXT NOT NULL,
    day       TEXT NOT NULL,
    price     REAL,
    currency  TEXT,
    seller    TEXT,
    captured_at TEXT,
    PRIMARY KEY (product, country, day)
);
"""

def init_db(path="prices.db"):
    conn = sqlite3.connect(path)
    conn.execute(DDL)
    conn.commit()
    return conn

def upsert_offers(conn, offers):
    sql = """
    INSERT INTO price_history
        (product, country, day, price, currency, seller, captured_at)
    VALUES (?, ?, ?, ?, ?, ?, ?)
    ON CONFLICT(product, country, day) DO UPDATE SET
        price=excluded.price,
        currency=excluded.currency,
        seller=excluded.seller,
        captured_at=excluded.captured_at;
    """
    for o in offers:
        day = o.captured_at[:10]  # YYYY-MM-DD
        conn.execute(sql, (o.title, o.country, day, o.price,
                           o.currency, o.seller, o.captured_at))
    conn.commit()

def price_trend(conn, product, country, days=14):
    cur = conn.execute(
        """SELECT day, price, currency FROM price_history
           WHERE product = ? AND country = ?
           ORDER BY day DESC LIMIT ?""",
        (product, country, days),
    )
    return cur.fetchall()

عملی طور پر دنوں کے درمیان عنوانات ملانا مشکل حصہ ہے، کیونکہ گوگل کے عنوانات ہر کیپچر میں کچھ بدل سکتے ہیں۔ چھوٹی واچ لسٹ کے لیے اسکریپ شدہ عنوان کو مستحکم کلید سمجھنے کے بجائے، اپسرٹ سے پہلے خام عنوانات کو اپنی بنائی ہوئی معیاری پروڈکٹ ID سے میپ کریں۔

آپ جاری قیمت کی نگرانی کو کیسے شیڈول کرتے ہیں؟

مانیٹرنگ شیڈول کرنے کے لیے فیچ، پارس اور اسٹور مراحل کو ایک انٹری پوائنٹ میں لپیٹیں اور اسے cron سے مقررہ وقفے پر چلائیں، تاکہ قیمتیں دستی رنز کے بغیر خود بخود تازہ ہوں۔ قیمت ٹریکنگ کے لیے دن میں ایک بار چلانا معقول ڈیفالٹ ہے؛ زیادہ کثرت زیادہ تر کیٹلاگز میں اضافی سگنل کم دیتی ہے مگر لاگت اور بلاک ہونے کا خطرہ بڑھا دیتی ہے۔

# run_monitor.py
def run_once(queries):
    conn = init_db()
    for query in queries:
        for market in MARKETS:
            rows = paginate(query, market, max_pages=3)
            offers = to_offers(rows, query, market["country"])
            export_csv(offers)
            upsert_offers(conn, offers)
            print(f"{query} / {market['country']}: {len(offers)} offers")
    conn.close()

if __name__ == "__main__":
    WATCHLIST = ["wireless headphones", "mechanical keyboard"]
    run_once(WATCHLIST)

پھر اسے cron میں رجسٹر کریں۔ نیچے دی گئی انٹری ہر روز 06:15 پر مانیٹر چلاتی ہے اور ڈیبگنگ کے لیے آؤٹ پٹ لاگ کرتی ہے، جو ضروری ہے کیونکہ شیڈول شدہ اسکریپر ورنہ خاموشی سے ناکام ہو سکتا ہے۔

# crontab -e
# minute hour day month weekday  command
15 6 * * * cd /opt/shopping && /usr/bin/python3 run_monitor.py >> monitor.log 2>&1

جاب کے اندر تھوڑا جٹر شامل کریں، مثلا شروع میں چند منٹ کی بے ترتیب نیند، تاکہ درخواستیں ہر روز عین اسی سیکنڈ پر گوگل تک نہ پہنچیں۔ اوپر بیان کیے گئے طریقے کے مطابق ایگزٹ ممالک گھمائیں، درخواستوں کی رفتار محدود رکھیں، اور لاگ پر نظر رکھیں کہ بلاکس کی شرح بڑھ تو نہیں رہی۔ یہ اس بات کی ابتدائی علامت ہو سکتی ہے کہ گوگل نے اپنے دفاع بدل دیے ہیں یا آپ کے پیٹرن بہت زیادہ باقاعدہ ہو گئے ہیں۔

آپ کو کون سا ڈیٹا جمع کرنے کا طریقہ منتخب کرنا چاہیے: DIY، پوشیدہ اینڈ پوائنٹس، SERP API، یا ہیڈ لیس؟

انتخاب اس بنیاد پر کریں کہ آپ کتنی نازکی اور انجینئرنگ خود سنبھال سکتے ہیں اور فی درخواست کتنی قیمت ادا کرنا چاہتے ہیں۔ ایک ہی درست جواب نہیں ہے؛ اصل tradeoff کنٹرول اور لاگت کے مقابلے میں دیکھ بھال کے بوجھ اور اینٹی باٹ exposure کا ہے۔

اینٹی باٹ حقیقت: گوگل ریٹ لمٹنگ، CAPTCHAs، رضامندی کی دیواروں، گھومتے ہوئے مبہم مارک اپ، اور رویے کے سگنلز سے ان نتائج کا فعال دفاع کرتا ہے۔ خود بنایا گیا کوئی بھی اسکریپر وقتا فوقتا ٹوٹے گا اور مسلسل دیکھ بھال مانگے گا۔ پراکسیز اور بیک آف بلاکس کم کرتے ہیں؛ ختم نہیں کرتے۔ جو بھی ہمیشہ ناقابل بلاک گوگل اسکریپر کا وعدہ کرے، وہ دعوی بڑھا چڑھا کر کر رہا ہے۔

طریقہ لاگت نزاکت کنٹرول
DIY HTML پارسنگ کم (صرف پراکسی) زیادہ مکمل
پوشیدہ JSON اینڈ پوائنٹس کم (صرف پراکسی) بہت زیادہ مکمل
SERP API زیادہ (فی درخواست) کم محدود
ہیڈ لیس براؤزر درمیانہ (کمپیوٹ + پراکسی) درمیانہ مکمل

SERP API بمقابلہ DIY: تھرڈ پارٹی SERP API شاپنگ نتائج کو پارس شدہ JSON کی صورت میں واپس کرتی ہے اور پارسنگ اور اَن بلاکنگ کا کام آپ سے لے لیتی ہے، لیکن اس کی فی درخواست قیمت ہوتی ہے، vendor lock-in آتا ہے، اور اس بات پر کم کنٹرول رہتا ہے کہ عین کیا فیچ کیا جا رہا ہے۔ پراکسیز پر اپنا اسکریپر چلانا فی درخواست کہیں سستا پڑتا ہے اور مکمل کنٹرول دیتا ہے، مگر پارسر، ری ٹرائیز، اور گوگل کی تبدیلیوں کے بعد دیکھ بھال آپ ہی کے ذمے رہتی ہے۔ DataImpulse کی جگہ واضح ہے: یہ ان DIY طریقوں کے نیچے پراکسی پرت ہے، SERP API یا منظم اسکریپنگ سروس نہیں۔ اگر آپ پارسنگ کا کام صفر چاہتے ہیں تو SERP API بہتر سفارش ہے؛ اگر کم لاگت اور کنٹرول چاہتے ہیں اور اسکریپر برقرار رکھ سکتے ہیں تو گھومتی ہوئی پراکسیز پر DIY معاشی طور پر بہتر ہے۔ پوشیدہ JSON اینڈ پوائنٹس اور بھی سستے پڑ سکتے ہیں، مگر سب سے زیادہ نازک بھی ہوتے ہیں کیونکہ گوگل انہیں بغیر اطلاع بدل یا ہٹا سکتا ہے۔

کیا گوگل شاپنگ کو اسکریپ کرنا قانونی اور اخلاقی ہے؟

عوامی طور پر دکھنے والے پروڈکٹ ڈیٹا کی اسکریپنگ عموما نجی یا محدود مواد تک رسائی کے مقابلے میں کم خطرہ سمجھی جاتی ہے، لیکن یہ قواعد سے آزاد نہیں، اور یہ قانونی مشورہ نہیں ہے۔ گوگل شاپنگ پر قیمتیں اور لسٹنگز عوامی ہیں، پھر بھی انہیں اکٹھا اور استعمال کرنے کا طریقہ اہم ہے، اور اپنے مخصوص کیس کی تصدیق کسی اہل وکیل سے کرنی چاہیے۔

  • سروس کی شرائط: خودکار رسائی گوگل کی شرائط سے ٹکرا سکتی ہے؛ یہ کاپی رائٹ یا کمپیوٹر رسائی کے قانون سے الگ ایک معاہداتی معاملہ ہے۔
  • ذاتی ڈیٹا: پروڈکٹ لسٹنگز عموما ذاتی ڈیٹا نہیں ہوتیں، لیکن جائزہ دینے والوں کے نام یا دوسرے شناختی اشارے جمع کرنے سے گریز کریں، اور جہاں لاگو ہو وہاں GDPR کی پیروی کریں۔
  • شرح اور بوجھ: درخواستوں کا حجم معقول رکھیں تاکہ جس سروس سے ڈیٹا لے رہے ہیں اس پر غیر ضروری بوجھ نہ پڑے۔
  • ڈیٹا کا استعمال: کاپی رائٹ والی تصاویر یا تفصیلات کو مکمل طور پر دوبارہ استعمال کرنا، قیمتوں کو حقائق کے طور پر تجزیہ کرنے سے کہیں زیادہ خطرناک ہے۔

ڈیٹا جمع کرنے کے پہلو سے اخلاقیات ان IPs سے شروع ہوتی ہے جو آپ استعمال کرتے ہیں۔ DataImpulse اپنی IPs ان صارفین سے حاصل کرتا ہے جو رضاکارانہ طور پر شامل ہوتے ہیں اور معاوضہ پاتے ہیں، GDPR کے مطابق کام کرتا ہے، اور ڈیٹا پروسیسنگ معاہدہ فراہم کرتا ہے، جس سے قابل دفاع پائپ لائن بنانے میں مدد ملتی ہے۔ رضامندی، سورسنگ، اور ذمہ دارانہ عمل کی مکمل تفصیل کے لیے ہماری گائیڈ اخلاقی ویب اسکریپنگ دیکھیں۔ اخلاقی IP سورس کو مناسب رفتار اور ڈیٹا کے محدود، حقیقت پر مبنی استعمال کے ساتھ ملائیں، تو قانونی اور ساکھ دونوں طرح کے خطرات کم رہتے ہیں۔

گوگل شاپنگ ڈیٹا حاصل کرنے کے طریقے

اکثر پوچھے گئے سوالات

کیا گوگل شاپنگ اسکریپ کرنے کے لیے رہائشی پراکسیز ضروری ہیں؟

رہائشی پراکسیز سب سے قابل اعتماد انتخاب ہیں کیونکہ یہ حقیقی صارف IPs استعمال کرتی ہیں جو عام ٹریفک میں گھل مل جاتی ہیں۔ ڈیٹا سینٹر پراکسیز کم حجم کے لیے کام کر سکتی ہیں، مگر انہیں پہچان کر بلاک کرنا آسان ہوتا ہے۔

میں گوگل شاپنگ سے مقامی قیمتیں کیسے حاصل کروں؟

gl اور hl پیرامیٹرز کو ہدف ملک اور زبان پر سیٹ کریں، اور ملک کے syntax سے درخواست کو اسی ملک کی پراکسی IP کے ذریعے روٹ کریں، مثلا جرمنی کے لیے __cr.de پر ختم ہونے والا یوزرنیم۔ گوگل پیرامیٹرز اور درخواست کی IP دونوں دیکھتا ہے تاکہ فیصلہ کرے کہ کون سی قیمتیں دکھانی ہیں۔

کیا DataImpulse گوگل شاپنگ اسکریپنگ API ہے؟

نہیں۔ DataImpulse پراکسی پرت، یعنی رہائشی، موبائل، اور ڈیٹا سینٹر IPs، فراہم کرتا ہے؛ یہ منظم اسکریپنگ یا SERP API نہیں۔ آپ اس کی IPs کے اوپر اپنا اسکریپر یا کوئی تھرڈ پارٹی ٹول چلاتے ہیں۔

میرا گوگل شاپنگ اسکریپر بار بار بلاک کیوں ہوتا رہتا ہے؟

گوگل ایک ہی IP سے آنے والی بار بار خودکار درخواستوں کو تھروٹل کرتا ہے اور CAPTCHAs یا رضامندی کی دیواریں دکھاتا ہے۔ گھومتی ہوئی رہائشی پراکسیز، حقیقت پسندانہ ہیڈرز، 429 جوابات پر ایکسپونینشل بیک آف، اور مناسب درخواست رفتار بلاکس کو بہت کم کرتے ہیں، اگرچہ کوئی طریقہ انہیں مکمل ختم نہیں کرتا۔

کیا مجھے SERP API استعمال کرنا چاہیے یا اپنا خود کا اسکریپر بنانا چاہیے؟

SERP API پارسنگ اور اَن بلاکنگ کا کام آپ سے لے لیتی ہے، مگر فی درخواست زیادہ لاگت اور کم کنٹرول کے ساتھ؛ یہ ان ٹیموں کے لیے موزوں ہے جو دیکھ بھال نہیں کرنا چاہتیں۔ گھومتی ہوئی پراکسیز پر اپنا اسکریپر بہت کم لاگت دیتا ہے اور مکمل کنٹرول بھی، لیکن گوگل کے بدلنے پر پارسر اور ری ٹرائیز برقرار رکھنا آپ کی ذمہ داری رہتا ہے۔

DataImpulse کب مناسب انتخاب نہیں؟

اگر آپ کو static ISP پراکسیز، مکمل طور پر منظم اسکریپنگ API، یا بینکنگ اور سرکاری سائٹس تک رسائی چاہیے، تو DataImpulse صحیح ٹول نہیں۔ اس کی توجہ عوامی ڈیٹا جمع کرنے اور مواد تک رسائی کے لیے گھومتی ہوئی رہائشی، موبائل، اور ڈیٹا سینٹر پراکسیز پر ہے۔

قابل بھروسہ پراکسیز کے ساتھ گوگل شاپنگ اسکریپنگ شروع کریں

اگر آپ مختلف مارکیٹوں میں گوگل شاپنگ کا ڈیٹا اکٹھا کرنے کے لیے تیار ہیں، تو DataImpulse آپ کو گھومتی ہوئی اور اسٹکی رہائشی، موبائل اور ڈیٹا سینٹر IPs دیتا ہے، ملک کی ٹارگٹنگ سمیت، فی جی بی ایک ڈالر سے شروع۔ اکاؤنٹ بنائیں اور اپنے پہلے اسکریپر کو صاف IP پول کے ذریعے روٹ کریں۔


Share article: