استخراج داده از وب (Web Scraping) یعنی اطلاعاتی را که داخل صفحات وب منتشر شدهاند، بهصورت خودکار جمع کنیم و به دادهای تبدیل کنیم که بتوان آن را جستوجو، تحلیل یا وارد یک سیستم دیگر کرد. هدف معمولاً ساخت یک خط لوله است: از منبع وب تا خروجی قابل اتکا برای محصول، CRM یا داشبورد.
- وباسکرپینگ برای صفحات استاتیک سادهتر است؛ سایتهای JavaScript اغلب به مرورگر headless یا API پنهان نیاز دارند.
- Crawler لینکها را پیمایش میکند؛ Scraper فیلدهای مشخص را از هر صفحه برمیدارد.
- اگر API رسمی و مجاز دارید، معمولاً اولویت با API است — نه پارس HTML.
- کیفیت داده (نرمالسازی، dedupe، lineage) مهمتر از «یک بار اجرا شدن اسکریپت» است.
- محدودیتهای فنی منبع (JS، session، rate limit، anti-bot) روی معماری و هزینه پروژه اثر مستقیم دارند.
استخراج داده از وب دقیقاً چه کار میکند؟
در سادهترین شکل، سه مرحله دارید: دریافت محتوا (HTTP یا مرورگر)، استخراج فیلدها از HTML/JSON، و ذخیره در فایل یا پایگاه داده. وقتی فروشگاهی ۵۰ هزار محصول دارد اما در هر صفحه فقط ۲۴ مورد نشان میدهد، باید مکانیزم صفحهبندی و نرخ درخواست را در طراحی job لحاظ کنید.
Crawler و Scraper — تفاوت عملی
Crawler مثل نقشهکش است: از یک URL شروع میکند، لینکهای داخلی را دنبال میکند و تصمیم میگیرد کدام صفحات وارد صف استخراج شوند. Scraper روی هر صفحه هدف کار میکند و مثلاً عنوان، قیمت و لینک را بیرون میکشد. در پروژه واقعی این دو در یک pipeline ادغام میشوند؛ اما اگر فقط ۱۰ URL مشخص دارید، شاید اصلاً crawler سنگین لازم نباشد.
قبل از نوشتن کد، لیست فیلدهای خروجی را ثابت کنید (schema). بدون schema، هر تغییر کوچک در سایت هدف کل پروژه را زمینگیر میکند.
HTML، DOM و جایی که داده «نشسته»
مرورگر HTML را به DOM تبدیل میکند — درختی از تگها که با CSS و JavaScript تغییر میکند. Scraper شما یا مستقیماً روی HTML پاسخ HTTP کار میکند، یا بعد از اجرای JavaScript در مرورگر headless به DOM دسترسی دارد. selectorهایی مثل data-testid یا کلاسهای ثابت معمولاً پایدارتر از ساختار تزئینی صفحه هستند.
صفحات استاتیک در برابر JavaScript
صفحه استاتیک محتوای اصلی را در HTML اولیه دارد؛ با requests و BeautifulSoup اغلب کافی است. اپلیکیشنهای React/Vue ممکن است HTML اولیه خالی بدهند و داده را با fetch پر کنند — آنجا یا باید Playwright/Selenium استفاده کنید یا همان endpoint JSON که فرانتاند صدا میزند را — در صورت دسترسی پایدار در معماری پروژه — مصرف کنید.
مثال کوتاه: استخراج یک فیلد از HTML
import requests
from bs4 import BeautifulSoup
url = "https://example.com/product/42"
resp = requests.get(url, timeout=30)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "lxml")
title = soup.select_one("h1.product-title")
price = soup.select_one("[data-price]")
print({"title": title.get_text(strip=True) if title else None,
"price": price.get_text(strip=True) if price else None})
این کد فرض میکند selectorها در HTML اولیه وجود دارند. اگر قیمت فقط بعد از JavaScript رندر شود، خروجی None میگیرید — نشانهای که باید لایه مرورگر یا API را بررسی کنید.
API در برابر Web Scraping
وقتی سرویس REST API رسمی دارد، داده معمولاً تمیزتر و پایدارتر است. Scraping وقتی معنا دارد که API عمومی ندارید، API با UI فرق دارد، یا باید همان چیزی را بگیرید که کاربر در صفحه میبیند. جزئیات بیشتر در مقاله API Scraping.
| معیار | API | Scraping HTML |
|---|---|---|
| پایداری ساختار | بالا (schema/version) | متوسط — وابسته به DOM |
| هزینه نگهداری | پایینتر در بلندمدت | بالاتر — تغییر layout |
| پوشش داده | محدود به قرارداد API | نزدیک به UI |
| قرارداد دسترسی | Terms API | ساختار HTML/API و سیاست crawling |
صفحهبندی (Pagination) و Infinite Scroll
دو الگوی رایج: پارامتر ?page=2 در URL، یا مسیرهایی مثل /page/2/. در حلقه استخراج، همیشه شرط توقف مشخص داشته باشید (صفحه خالی، تکرار URL، یا سقف صفحه). لیست بیانتها با scroll در Playwright یا API پنهان — جزئیات در مقاله Pagination و Infinite Scroll.
احراز هویت و Session
برخی منابع بدون login داده کامل نمیدهند. الگوها: cookie session، Bearer token، OAuth refresh. توکنها را در env نگه دارید؛ session را مثل secret مدیریت کنید و expiry را در پایش خطا ببینید (۴۰۱ ناگهانی).
کیفیت داده: تمیز کردن و نرمالسازی
خروجی خام معمولاً قابل تحلیل نیست. قیمت با «تومان» و کاما، تاریخ شمسی و میلادی مخلوط، URL نسبی — همه باید قبل از ذخیره یکسان شوند. راهنمای عملی در پاکسازی و نرمالسازی داده.
حذف تکرار (Deduplication)
همان آگهی یا محصول ممکن است چند URL داشته باشد. کلید یکتا (مثلاً شناسه منبع + SKU) تعریف کنید و upsert کنید — نه insert بیقید. برای merge رکوردها از timestamp آخرین crawl استفاده کنید.
برای هر رکورد lineage ثبت کنید: منبع، زمان استخراج، نسخه selector.
{
"title": "نمونه محصول",
"price_toman": 1200000,
"url": "https://example.com/p/42",
"scraped_at": "2026-03-19T08:00:00Z"
}
نمونه نمایشی — ساختار پیشنهادی رکورد
ذخیرهسازی و زمانبندی
برای تحلیل سبک، CSV/JSON کافی است. برای محصول، PostgreSQL + ایندکس روی کلید یکتا رایج است. زمانبندی با cron، Celery Beat یا scheduler ابری. job هر شب ساعت ۲ اجرا شود، اما اگر منبع down بود retry با backoff داشته باشید.
پایش
حداقل: زمان اجرا، تعداد رکورد، نرخ خطا HTTP، تعداد selector miss. baseline هفتگی بگیرید — اگر ناگهان ۹۰٪ صفحات خالی شدند، احتمالاً layout عوض شده نه «شبکه بد». بیشتر در مدیریت خطا و پایداری.
محدودیت تعداد درخواست (Rate limiting)
Rate limit میتواند پاسخ ۴۲۹ یا ۵۰۳ بدهد؛ در معماری استخراج throttle، jitter، backoff و کاهش concurrency را از اول طراحی کنید. نرخ پردازش باید با حجم داده، SLA و رفتار واقعی منبع همخوان باشد.
ضدربات و پروکسی (مفهومی)
CAPTCHA، fingerprint مرورگر، WAF و بلاک IP روی انتخاب ابزار (Requests در برابر Playwright)، pool پروکسی و هزینه نگهداری اثر میگذارند. راهحل پایدار ترکیب selector مقاوم، retry هوشمند، پایش drift و — در صورت نیاز — لایه پروکسی در معماری resilience است.
ملاحظات فنی، پایداری و دسترسی
robots.txt فایلی است که برخی سایتها برای اعلام ترجیحات crawling منتشر میکنند؛ در امکانسنجی روی مسیر URL و سیاست نرخ درخواست اثر میگذارد. برای منابع پیچیده (JS، session، pagination چندمرحلهای) روش استخراج بر اساس معماری واقعی صفحه طراحی میشود — از HTML ساده تا مرورگر خودکار و تحلیل endpoint شبکه.
BeautifulSoup و پارسر HTML
BeautifulSoup روی رشته HTML کار میکند؛ با lxml یا html.parser سریع parse میکند. برای صفحات استاتیک با Requests ترکیب ایدهآل است. محدودیت: اگر DOM بعد از JavaScript ساخته شود، باید ابتدا HTML رندرشده از Playwright بگیرید.
ابزارهای Python — چه زمانی کدام؟
- Requests + BeautifulSoup: حجم کم، HTML استاتیک، prototype سریع.
- Scrapy: crawl مقیاسپذیر، queue داخلی، middleware برای proxy و retry، export pipeline.
- Playwright: SPA، login، infinite scroll — مقایسه با Selenium.
- Selenium: legacy یا Grid سازمانی؛ برای پروژه سبز اغلب Playwright اولویت دارد.
اشتباهات رایج
- selector روی کلاسهای تزئینی که هر deploy عوض میشوند.
- نداشتن golden HTML برای regression بعد از تغییر سایت هدف.
- ذخیره HTML کامل برای میلیون رکورد بدون نیاز واقعی.
- یک job بدون idempotency که duplicate ایجاد میکند.
هوش مصنوعی در این مسیر
مدلهای زبانی میتوانند فیلد از متن آزاد پیشنهاد دهند یا وقتی layout عوض شد کمک کنند — اما عدد و قیمت را بدون validation قبول نکنید. در هوش مصنوعی در Web Scraping hybrid rule+model را باز کردهایم.
کاربردهای رایج در پروژههای ایرانی
پایش قیمت مارکتپلیس، آرشیو خبر، dataset املاک، فرصت شغلی، lead B2B — هر کدام schema و SLA متفاوت دارد. برای استخراج فروشگاه، سرویس جمعآوری اطلاعات فروشگاهی و برای پروژه سفارشی توسعه Scraper اختصاصی را ببینید.
سوالات متداول
آیا همه سایتها قابل استخراج هستند؟
از نظر فنی بسیاری بله؛ پایداری و هزینه به ساختار صفحه، anti-bot، rate limit، نیاز به session و نگهداری selector بستگی دارد.
خروجی معمول چیست؟
CSV، JSON، PostgreSQL، یا API داخلی — بسته به مصرفکننده بعدی (داشبورد، CRM، مدل ML).
اگر ساختار سایت عوض شود چه میشود؟
selectorها بهروز میشوند؛ داشتن تست regression روی HTML ذخیرهشده زمان رفع را کم میکند.
چطور شروع کنم؟
یک منبع کوچک، ۳–۵ فیلد، یک job زمانبندیشده، مانیتور ساده — بعد scale.
قدم بعدی شما
مسیر API: راهنمای API یا API در برابر Scraping. صفحات JavaScript: Playwright. زمانبندی: اتوماسیون. trade-off بین سرعت تحویل، هزینه نگهداری و ریسک بلاک را explicit بنویسید.
برای پیادهسازی در مقیاس تیم، درخواست پروژه بدهید یا محصولات آماده را در فروشگاه ببینید.