Python Programming

اسکرپینگ ترکیبی: BeautifulSoup و Selenium

در مهندسی داده‌های مدرن، تکیه بر یک روش اسکرپینگ وب به ندرت کافی است. تجزیه HTML استاتیک بسیار سریع است، اما زمانی که محتوا توسط جاوااسکریپت رندر شود، شکست می‌خورد. در مقابل، مرورگرهای بدون سرور (headless) قدرتمند اما پرمصرف و کند هستند. برای پایپ‌لاین‌های داده در مقیاس بزرگ، استراتژی بهینه یک معماری ترکیبی است که از سرعت BeautifulSoup برای محتوای استاتیک و قدرت Selenium برای عناصر پویا بهره می‌برد.

چرا رویکرد ترکیبی؟

تصمیم برای ترکیب این ابزارها ناشی از نقاط قوت مکمل آن‌هاست. BeautifulSoup اسناد HTML را با استفاده از یک تجزیه‌گر مانند lxml یا html5lib تجزیه می‌کند. این کتابخانه کاملاً پایتونی و بسیار کارآمد است و برای پردازش هزاران صفحه ساده که داده‌ها در پاسخ HTTP اولیه موجود هستند، ایده‌آل می‌باشد. با این حال، اگر تلاش کنید تا از برنامه‌های تک‌صفحه‌ای (SPA) مدرن اسکرپینگ انجام دهید، BeautifulSoup تنها پوسته خالی صفحه را قبل از اجرای جاوااسکریپت بازگردانی می‌کند.

Selenium از سوی دیگر، یک مرورگر واقعی را خودکارسازی می‌کند. این ابزار منتظر می‌ماند تا جاوااسکریپت DOM را رندر کند و به شما امکان می‌دهد داده‌هایی را استخراج کنید که به تعامل کاربر یا بارگذاری ناهمگام (async) وابسته هستند. نقطه ضعف آن چیست؟ این ابزار به یک موتور مرورگر کامل، حافظه قابل توجه و چرخه‌های CPU نیاز دارد. با ترکیب آن‌ها، می‌توانید Selenium را تنها در صورت نیاز استفاده کرده و برای تجزیه سریع منبع رندر شده یا برای صفحات بعدی که به اجرای JS نیاز ندارند، به BeautifulSoup روی بیاورید.

راه‌اندازی محیط

قبل از نوشتن کد، اطمینان حاصل کنید که کتابخانه‌های لازم نصب شده‌اند. شما به requests برای مدیریت HTTP پایه، beautifulsoup4 برای تجزیه و selenium برای خودکارسازی مرورگر نیاز دارید. همچنین به WebDriver مناسب برای مرورگر خود (مثلاً ChromeDriver) نیاز دارید.

در اینجا یک راه‌اندازی اولیه برای مقداردهی اولیه درایور Selenium با گزینه‌های headless جهت صرفه‌جویی در منابع آورده شده است:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)

پیاده‌سازی استراتژی ترکیبی

منطق اصلی رویکرد ترکیبی شامل یک بررسی است. هنگامی که یک URL را درخواست می‌کنید، ابتدا تلاش می‌کنید محتوای استاتیک را تجزیه کنید. اگر داده‌های هدف گم شده باشند یا نشانگرهای پویا را تشخیص دهید (مانند کانتینرهای خالی که داده‌ها باید در آن‌ها باشند)، به Selenium روی می‌آورید. به عنوان جایگزین، می‌توانید یک لیست جداگانه از URLهای شناخته شده که به رندر پویا نیاز دارند نگهداری کنید و ابزار مناسب را بر اساس منبع اعمال کنید.

در زیر یک مثال عملی از نحوه یکپارچه‌سازی BeautifulSoup با خروجی Selenium آورده شده است. درایور Selenium کد منبع رندر شده را ارائه می‌دهد که سپس برای استخراج تمیز و سریع به BeautifulSoup داده می‌شود:

from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By

def scrape_page(url):
    # استفاده از Selenium برای دریافت HTML کاملاً رندر شده
    driver.get(url)
    rendered_html = driver.page_source
    
    # ارسال HTML رندر شده به BeautifulSoup برای تجزیه
    soup = BeautifulSoup(rendered_html, 'html.parser')
    
    # مثال: استخراج عنوان پویا یا عنصر
    title = soup.find('h1', class_='dynamic-title').text
    return title

بهینه‌سازی برای مقیاس

هنگام استقرار این معماری در یک پایپ‌لاین تولیدی، کارایی کلیدی است. از ایجاد یک WebDriver جدید برای هر درخواست خودداری کنید، زیرا زمان راه‌اندازی قابل توجه است. در عوض، از یک اتصال پوول (connection pool) یا سرویسی مانند Selenium Grid برای مدیریت نمونه‌های مرورگر استفاده کنید. علاوه بر این، همیشه انتظارهای صریح (explicit waits) را در Selenium تنظیم کنید تا از شرایط رقابتی (race conditions) جلوگیری کنید که در آن‌ها تلاش می‌کنید عناصری را قبل از بارگذاری کامل آن‌ها اسکرپینگ کنید.

علاوه بر این، در نظر بگیرید که مدیریت خطا و منطق تلاش مجدد را پیاده‌سازی کنید. ناپایداری شبکه یا خرابی‌های موقت مرورگر در اسکرپینگ در مقیاس بزرگ رایج است. یک مکانیزم تلاش مجدد قوی تضمین می‌کند که پایپ‌لاین شما مقاوم باقی بماند.

نتیجه‌گیری

پذیرش یک معماری اسکرپینگ ترکیبی به شما امکان می‌دهد تا سرعت و قابلیت را متعادل کنید. با استفاده از BeautifulSoup برای کارهای سنگین در صفحات استاتیک و Selenium تنها برای اهداف پیچیده و پر از جاوااسکریپت، می‌توانید پایپ‌لاین‌های داده‌ای بسازید که هم سریع و هم قابل اعتماد باشند. این رویکرد هزینه‌های محاسباتی را به حداقل رسانده و در عین حال مقدار داده‌های قابل استخراج از وب را به حداکثر می‌رساند.

Share: