

استخراج نتایج جستجوی گوگل (SERP) یکی از کاربردیترین مهارتها برای سئو، تحلیل رقبا، تحقیق کلمات کلیدی، مانیتورینگ برند و حتی ساخت دیتاستهای تحقیقاتی است. ایده ساده است: یک عبارت را در گوگل جستجو میکنید، لینکها و عنوانها و توضیحات را میبینید، و حالا میخواهید همین کار را با پایتون و بهصورت خودکار انجام دهید.
اما در عمل، اسکرپ گوگل مثل اسکرپ یک وبسایت ساده نیست: ساختار HTML پیچیده و تو در توست، بخشهایی مثل تبلیغات و باکسهای ویژه ممکن است قاطی نتایج شوند، و مهمتر از همه گوگل بهشدت روی تشخیص رباتها حساس است. در این مقاله یک مسیر «واقعبینانه» برای ساخت اسکرپر SERP با پایتون میسازیم: از ساخت URL و پارس HTML تا صفحهبندی، ریتلیمیت، و پایدارسازی. اگر هدفتان استفاده پایدار و مقیاسپذیر است، در انتهای مقاله هم راهکار آمادهتر را معرفی میکنیم (از جمله اسکریپر گوگل سرچ Asanscrape).

وقتی وارد گوگل میشوید و یک کلمه را سرچ میکنید، خروجی فقط «۱۰ لینک آبی» نیست. بسته به نوع کوئری، ممکن است با این اجزا روبهرو شوید: نتایج ارگانیک، تبلیغات، باکس People Also Ask، فیچر اسنیپت، ویدیو/تصویر، نقشه، سایتلینکها، باکسهای خبری و دهها ماژول دیگر. هر کدام میتوانند HTML متفاوتی داشته باشند.
چالش اصلی اینجاست که گوگل برای جلوگیری از سوءاستفاده، ساختار صفحه را دائماً تغییر میدهد و از کلاسهای CSS پویا (Dynamic) استفاده میکند؛ یعنی اگر اسکرپر شما به کلاسها یا سلکتورهای شکننده وابسته باشد، خیلی زود میشکند. بنابراین معمولاً بهتر است روی نشانههای پایدارتر (مثل وجود تگ h3 برای عنوان نتیجه، یا الگوی لینکها) تکیه کنید و در عین حال آماده تغییرات باشید.
از طرف دیگر، گوگل رفتارهای غیرعادی را سریع تشخیص میدهد: درخواستهای زیاد از یک IP، هدرهای غیرواقعی، پارامترهای عجیب مثل درخواست ۱۰۰ نتیجه در هر صفحه، یا تکرار بیش از حد یک الگو میتواند باعث نمایش CAPTCHA یا بلاک شدن شود.
.jpg)
قبل از اینکه وارد کدنویسی شوید، سه نکته را جدی بگیرید:
اگر هدف شما فقط «یادگیری» است، ساخت اسکرپر آموزشی عالی است. اما اگر هدف شما «استفاده پایدار در محصول/کسبوکار» است، معمولاً APIهای آماده یا سرویسهای تخصصی (که مدیریت پروکسی/کپچا/پایداری را انجام میدهند) هزینه را بهشدت کاهش میدهند. در بخش پایانی، نمونه عملی استفاده از API را میبینید.
برای اینکه اسکرپر شما از یک اسکریپت ساده به یک ابزار قابل اتکا نزدیک شود، بهتر است معماری را اینطور ببینید:
اگر این معماری را درست بچینید، بعداً میتوانید منبع داده را هم عوض کنید: مثلاً به جای پارس HTML، از یک سرویس آماده استفاده کنید و همچنان بقیه پایپلاین شما (ذخیرهسازی، تحلیل، مانیتورینگ) بدون تغییر باقی بماند. این دقیقاً جایی است که سرویسهایی مثل Google Search Scraper در Asanscrape میتوانند نقش «Request + Anti-block + Pagination» را سادهتر کنند.
.jpg)
در این بخش یک اسکرپر «ساده اما قابل توسعه» میسازیم. هدف ما استخراج نتایج ارگانیک رایج است: عنوان (Title)، لینک (URL)، و در صورت امکان اسنیپت (Snippet). توجه کنید که HTML گوگل ثابت نیست؛ پس این کد را باید یک نقطه شروع بدانید، نه یک راهحل ابدی.
۱) نصب پیشنیازها
pip install requests beautifulsoup4 lxml
۲) ساخت URL جستجو
حداقل چیزی که نیاز دارید پارامتر q است. برای صفحهبندی معمولاً از start استفاده میشود (مثلاً ۰، ۱۰، ۲۰). برای کنترل تعداد نتایج هم پارامتر num وجود دارد (گاهی تا ۱۰۰ هم درخواست میشود، ولی ممکن است باعث بلاک یا خروجی ناقص شود).
۳) ارسال درخواست با هدرهای واقعی
حداقل یک User-Agent واقعی بگذارید. همچنین تایماوت و مدیریت خطا را فراموش نکنید.
۴) پارس کردن HTML و استخراج نتیجهها
در بسیاری از حالتها، عنوان نتیجه داخل h3 است و لینک داخل a. اما لینکهای گوگل گاهی ریدایرکت هستند (مثل /url?q=...) و باید URL واقعی را از پارامتر q بیرون بکشید.
import time
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse, parse_qs, urljoin
GOOGLE_BASE = "https://www.google.com/search"
def extract_real_url(href: str) -> str:
"""
لینکهای گوگل ممکن است به شکل /url?q=https://example.com&sa=...
باشند. این تابع URL واقعی را بیرون میکشد.
"""
if not href:
return ""
full = urljoin("https://www.google.com", href)
parsed = urlparse(full)
qs = parse_qs(parsed.query)
if "q" in qs and qs["q"]:
return qs["q"][0]
if parsed.scheme in ("http", "https") and parsed.netloc:
return full
return full
def build_google_url(query: str, start: int = 0, num: int = 10) -> str:
return f"{GOOGLE_BASE}?q={requests.utils.quote(query)}&start={start}&num={num}"
def scrape_google_page(query: str, start: int = 0, num: int = 10, sleep_s: float = 1.0):
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/122.0.0.0 Safari/537.36"
),
"Accept-Language": "fa-IR,fa;q=0.9,en-US;q=0.8,en;q=0.7",
}
url = build_google_url(query, start=start, num=num)
r = requests.get(url, headers=headers, timeout=20)
r.raise_for_status()
soup = BeautifulSoup(r.text, "lxml")
results = []
seen = set()
for h3 in soup.find_all("h3"):
a = h3.find_parent("a")
if not a or not a.get("href"):
continue
raw_href = a.get("href")
real_url = extract_real_url(raw_href)
title = h3.get_text(strip=True)
if not real_url.startswith("http"):
continue
if "google.com" in urlparse(real_url).netloc:
continue
key = (title, real_url)
if key in seen:
continue
seen.add(key)
snippet = ""
container = h3.find_parent("div")
if container:
text = container.get_text(" ", strip=True)
if text and title in text:
snippet = text.replace(title, "", 1).strip()
results.append({
"title": title,
"url": real_url,
"snippet": snippet
})
time.sleep(sleep_s)
return results
if __name__ == "__main__":
data = scrape_google_page("اسکرپ گوگل با پایتون", start=0, num=10)
for i, item in enumerate(data, 1):
print(i, item["title"], item["url"])
مراحل اجرای عملی (چکلیست)
وقتی از «یک صفحه» عبور میکنید، تازه چالش واقعی شروع میشود. اینجا چند نکته کلیدی برای مقیاس و پایداری:
۱) صفحهبندی با start و num
گوگل معمولاً نتایج را دستههای حدود ۱۰تایی میدهد. بنابراین برای رفتن به صفحه بعدی، start را به صورت ۰، ۱۰، ۲۰، ۳۰… تنظیم کنید. اگر num را تغییر میدهید، بهتر است start هم متناسب با همان افزایش یابد (مثلاً start=page*num).
۲) کنترل لوکیشن (کشور/منطقه)
نتایج گوگل وابسته به لوکیشن هستند. یکی از پارامترهای رایج برای شبیهسازی کشور، gl است (مثلاً gl=US برای آمریکا). برای پروژههای حساستر به لوکیشن، معمولاً باید علاوه بر پارامترها، IP/پروکسی را هم متناسب با همان کشور تنظیم کنید تا نتایج طبیعیتر شوند.
۳) ضدبلاک (Anti-bot) به زبان ساده
۴) همزمانی (Concurrency) با احتیاط
همزمانی میتواند سرعت را بالا ببرد، ولی اگر کنترل نشود خیلی سریع شما را وارد محدوده رفتار مشکوک میکند. اگر همزمانی میخواهید، تعداد تردها کم باشد و حتماً با پروکسی/ریتلیمیت همراه شود.
from concurrent.futures import ThreadPoolExecutor, as_completed
def scrape_many_pages(query: str, pages: int = 3, num: int = 10, max_workers: int = 3):
starts = [p * num for p in range(pages)]
all_results = []
with ThreadPoolExecutor(max_workers=max_workers) as ex:
futures = [ex.submit(scrape_google_page, query, start=s, num=num, sleep_s=1.0) for s in starts]
for f in as_completed(futures):
try:
all_results.extend(f.result())
except Exception as e:
print("Page failed:", e)
uniq = {}
for r in all_results:
uniq[r["url"]] = r
return list(uniq.values())
اگر خروجیتان را ذخیره نکنید، اسکرپ کردن عملاً ارزش عملی کمی دارد. سادهترین گزینه CSV است؛ اما برای پروژههای جدیتر، JSON و دیتابیس منطقیتر میشود.
import csv
from pathlib import Path
def save_to_csv(filename: str, rows: list[dict]):
path = Path(filename)
if not rows:
return
write_header = not path.exists()
with path.open("a", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=rows[0].keys())
if write_header:
w.writeheader()
w.writerows(rows)
اگر هدف شما «استفاده پایدار» است (نه فقط تمرین آموزشی)، معمولاً چالشهای اصلی اینها هستند: بلاک و کپچا، مدیریت پروکسی و لوکیشن، صفحهبندی قابل اعتماد، و خروجی ساختیافته. اینجا دقیقاً جایی است که Asanscrape بهعنوان یک API آماده کمک میکند: شما به جای جنگیدن با HTML و ضدباتها، یک درخواست API میزنید و خروجی JSON ساختیافته تحویل میگیرید.
.jpg)
Asanscrape چه کمکی میکند؟
لینک داخلی مهم: اگر دقیقاً دنبال اسکرپ نتایج گوگل هستید، این صفحه مربوط به ربات گوگل سرچ در Asanscrape است: اسکریپر گوگل سرچ. همچنین اگر میخواهید همه رباتها/اسکرپرهای آماده را ببینید: لیست همه اسکرپرها.
نمونه استفاده از API اسنسکرپ (Robot: google search)
import requests
BASE_URL = "[https://backend.asanscrape.com](https://backend.asanscrape.com)"
API_KEY = ""
url = f"{BASE_URL}/robots/create/task/wait-for-result/"
headers = {
"accept": "*/*",
"Authorization": f"token {API_KEY}",
"Content-Type": "application/json"
}
payload = {
"robot": "google search",
"inputs": {
"keyword": "asanscrape",
"domain": "google.com",
"from_": "2024-01-01 (optional)",
"to_": "2024-12-31 (optional)"
},
"pagination_token": "NEXT_TOKEN (optional)"
}
response = requests.request("POST", url, headers=headers, json=payload)
print(response.json()) نمونه خروجی (Example Response)
{
"data": {
"request": {
"status": true,
"status_code": 200,
"request_data": "{\"count\": 1.0, \"keyword\": \"\\u062f\\u0627\\u062f\\u0647 \\u0627\\u0633\\u062a\\u062e\\u0631\\u0627\\u062c\", \"domain\": \"google.com\"}"
},
"response": [
{
"title": "استخراج داده چیست؟ روشها و تکنیکهای موثر",
"url": "https://****/پردازش-داده-ها/استخراج-داده-data-extraction-چیست؟/",
"snippet": "Oct 14, 2025 — استخراج داده فرآیند جمعآوری سیستماتیک دادهها ...",
"favicon_text": "****"
}
],
"next_page_token": "gAAAAABpnkN6..."
},
"error": {}
}
چطور در پروژهتان از Asanscrape استفاده کنید؟
جمعبندی: ساخت اسکرپر دستی با پایتون برای یادگیری فوقالعاده است (و در پروژههای کوچک هم جواب میدهد)، اما برای مقیاس و پایداری، بهترین تصمیم معمولاً این است که «مسائل زیرساختی و ضدبات» را به یک سرویس تخصصی بسپارید. اگر میخواهید سریعتر، مطمئنتر و با خروجی ساختیافتهتر به دادههای SERP برسید، API اسنسکرپ مسیر را کوتاه و پایدار میکند.
لینکهای داخلی پیشنهادی برای ادامه مسیر:

