خانه/مقالات/راهنمای سریع XPath برای وب اسکریپینگ با Playwright
وب اسکریپینگ
سلنیوم
Playwright
برگشت به صفحه مقاله ها
راهنمای سریع XPath برای وب اسکریپینگ با Playwright

راهنمای سریع XPath برای وب اسکریپینگ با Playwright

این راهنمای عملی به شما نشان می‌دهد چگونه با Playwright در پایتون از XPath برای پیدا کردن عناصر، انتظار برای ظهور آنها، کلیک، اسکرین‌شات، اسکرول اتوماتیک و استخراج داده‌ها استفاده کنید؛ همراه با مثال‌های کدی، توضیح توابع و بهترین‌روش‌ها برای وب اسکریپینگ پایدار.
امیر حسین حسینیان
امیر حسین حسینیان
1404-10-15

مقدمه

در این مقاله به صورت عملی و مرحله‌به‌مرحله یاد می‌گیرید چگونه از XPath در ترکیب با Playwright برای وب اسکریپینگ (یا به‌اختصار «اسکریپ کردن») استفاده کنید. فرض می‌کنیم شما توسعه‌دهنده پایتون در سطح متوسط هستید و دنبال مثال‌های واقعی، نکات عملکردی و بهترین‌روش‌ها هستید. در پایان این مقاله می‌توانید عناصر صفحه را با XPath پیدا کنید، برای آنها صبر کنید، کلیک کنید، متن استخراج کنید، اسکرول اتوماتیک انجام دهید و سناریوهای ورود به‌حساب و استخراج داده را پیاده‌سازی کنید.

مبانی XPath و چرا در وب اسکریپینگ کاربردی است

XPath زبانی برای پیمایش در ساختار درختی XML/HTML است. وقتی عناصر دارای شناسه یا کلاس قابل اتکا نیستند، XPath به شما امکان می‌دهد بر اساس موقعیت، متن، صفت‌ها یا روابط بین نودها هدف‌گیری دقیق‌تری داشته باشید. در وب اسکریپینگ، این دقت زمانی که ساختار صفحه پیچیده یا دینامیک است بسیار مفید است.

درک سینتکس پایه XPath

چند مثال ساده از اجزای معمول:

  • //div — همه <div>‌ها در صفحه
  • //h3[@class='country-name'] — هر h3 که کلاس آن برابر country-name است
  • //a[contains(text(), 'Login')] — هر لینک که متن آن شامل «Login» است
  • (//ul/li)[1] — اولین <li> در هر <ul>

دو نوع XPath داریم: Absolute (مسیر کامل از ریشه، شکننده) و Relative (قابل نگهداری‌تر). در اغلب اسکریپ‌ها relative XPath توصیه می‌شود.

پیدا کردن XPath: DevTools و بازرسی دستی

روش سریع: در مرورگر روی عنصر راست‌کلیک → Inspect → راست‌کلیک روی عنصر در DevTools → Copy → Copy XPath یا Copy full XPath. معمولاً Copy XPath یک مسیر نسبی مفید می‌دهد و Copy full XPath مسیر مطلقی خواهد بود که مستعد شکست با تغییرات صفحه است.

روش دستی: از یک جد (ancestor) پایدار شروع کنید، سپس با استفاده از نام تگ‌ها، صفت‌ها و توابع مانند contains() یا starts-with() مسیرهای مقاوم بسازید.

مثال خروجی از DevTools:
//*[@id="countries"]/div/div[4]/div[1]/h3
یا مسیر مطلق:
/html/body/div/section/div/div[4]/div[1]/h3

Selecting Elements با Playwright (پایتون)

در Playwright پایتون معمولاً از API همگام (sync) یا ناهمگام (async) استفاده می‌کنیم. برای مثال‌های آموزشی از API همگام استفاده می‌کنیم تا خواناتر باشد. یک الگوی متداول برای گرفتن متن یک عنصر با XPath:

from playwright.sync_api import sync_playwright

def get_country():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        page.goto("https://www.scrapethissite.com/pages/simple/")

        # استفاده از XPath داخل locator
        locator = page.locator("xpath=//*[@id='countries']/div/div[4]/div[1]/h3")
        text = locator.inner_text()
        print(text)  # خروجی: Andorra

        browser.close()

get_country()

توضیح ورودی/خروجی و نقش توابع:

  • sync_playwright(): شروع ران‌تایم Playwright.
  • p.chromium.launch(): اجرای مرورگر Chromium؛ آرگومان headless قابل تنظیم است.
  • page.goto(url): پیمایش به آدرس مشخص.
  • page.locator(selector): برمی‌گرداند یک Locator که قبل از هر action به عنصر حل می‌شود.
  • locator.inner_text(): متن نمایش داده‌شده داخل عنصر را برمی‌گرداند.

استخراج چند مقدار (مثال جمع‌آوری نام کشورها)

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://www.scrapethissite.com/pages/simple/")

    locator = page.locator("xpath=//h3")
    names = locator.all_text_contents()  # تمام متن‌های h3 را به صورت لیست برمی‌گرداند
    print(names)

    browser.close()

توضیح: all_text_contents() لیستی از رشته‌ها برمی‌گرداند؛ جایگزین مناسب برای evaluateAll در نسخه‌های JS است و ساده‌تر از اجرای اسکریپت در صفحه.

منتظر ماندن برای XPath (انتظار صریح)

Playwright اغلب خودش منتظر بارگذاری می‌ماند اما در صفحات با محتوای دینامیک باید صریح‌تر عمل کنید. نمونه:

# انتظار برای XPath مشخص
page.wait_for_selector("xpath=//*[@class='product_pod']/h3", timeout=10000)

# سپس می‌توانید locator را استفاده کنید
product_titles = page.locator("xpath=//*[@class='product_pod']/h3").all_text_contents()

نکات: زمان timeout پیش‌فرض را در مواقع لازم افزایش دهید، اما از مقدارهای بسیار بلند دوری کنید تا منابع بلااستفاده نگهداری نشوند.

انجام عمل‌ها با XPath: کلیک، پر کردن فرم و اسکرین‌شات

مثال کلیک روی لینکی که متن خاصی دارد:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://www.demoblaze.com/")

    link_xpath = "xpath=//a[contains(., 'Samsung galaxy s6')]
"
    page.wait_for_selector(link_xpath)
    page.click(link_xpath)
    page.wait_for_load_state("networkidle")
    page.screenshot(path="s6.png", full_page=True)
    browser.close()

توضیح: در page.click() از selector مبتنی بر XPath استفاده می‌کنیم؛ ابتدا عنصر را صبر می‌کنیم تا ظاهر شود سپس کلیک می‌کنیم تا از race condition جلوگیری شود.

اسکرول اتوماتیک برای بارگذاری محتوای تنبل (lazy-loading)

import time
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com/long-page")

    previous_height = 0
    while True:
        page.evaluate("window.scrollBy(0, window.innerHeight);")
        time.sleep(2)
        current_height = page.evaluate("() => document.documentElement.scrollHeight")
        if current_height == previous_height:
            break
        previous_height = current_height

    # بعد از اسکرول، عناصر جدید قابل هدف‌گیری با XPath خواهند بود
    browser.close()

نکته: از sleep‌های کوتاه استفاده کنید و اگر امکان دارد از رویدادهای لود شبکه (wait_for_load_state) ترکیب کنید تا بیشتر قابل اعتماد شود.

مثال واقعی: ورود (Automated Authentication) با XPath

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://demo.applitools.com/")

    page.locator("xpath=//input[@id='username']").fill("myuser")
    page.locator("xpath=//input[@id='password']").fill("mypass")
    page.locator("xpath=//a[@id='log-in']").click()
    page.wait_for_load_state("networkidle")
    page.screenshot(path="login-screenshot.png")
    browser.close()

ورودی‌ها: رشته نام کاربری و رمز عبور. خروجی: عکس صفحه پس از ورود و معمولاً یک تغییر وضعیت در DOM که نشان‌دهنده ورود موفق است. همیشه اطلاعات حساس را در متغیرهای محیطی یا vault ذخیره کنید و در کد صریح قرار ندهید.

استخراج ساختاریافته: مثال فهرست کتاب

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://books.toscrape.com/catalogue/page-1.html")

    containers = page.locator("xpath=//ol[@class='row']/li")
    results = []
    for i in range(containers.count()):
        item = containers.nth(i)
        name = item.locator("xpath=.//h3/a").inner_text()
        price = item.locator("xpath=.//p[@class='price_color']").inner_text()
        rating_class = item.locator("xpath=.//p[contains(@class,'star-rating')]").get_attribute("class")
        rating = rating_class.split()[-1] if rating_class else ""
        results.append({"name": name, "price": price, "rating": rating})

    print(results)
    browser.close()

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

بهترین‌روش‌ها و نکات عملکردی

  • از XPathهای نسبتاً کوتاه و هدف‌دار استفاده کنید: به جای مسیرهای طولانی که از شاخص‌های عددی زیاد استفاده می‌کنند، به دنبال صفت‌های منحصر به فرد یا ترکیب contains() باشید.
  • از مسیرهای مطلق دوری کنید: شکننده‌اند و با کوچک‌ترین تغییر DOM می‌شکنند.
  • صبر و زمان‌بندی مناسب: از wait_for_selector یا خودِ Locator.wait_for برای جلوگیری از race condition استفاده کنید.
  • تعامل با صفحات دینامیک: اگر محتوای صفحه از طریق XHR/Fetch بارگذاری می‌شود، ترکیب wait_for_load_state('networkidle') یا صبر برای یک عنصر شاخص را در نظر بگیرید.
  • مدیریت خطا و retry: شبکه و تغییرات صفحه باعث خطا می‌شود؛ درخواست‌ها و عملیات DOM را با try/except احاطه کنید و مکانیزم retry (با backoff) اضافه کنید.
  • پرفورمنس: از انتخاب‌کننده‌های ناکارا که تمام درخت را جست‌وجو می‌کنند پرهیز کنید؛ محدود کردن جست‌وجو با یک ancestor پایدار کارایی را بهبود می‌دهد.
  • امنیت و رعایت قوانین: قبل از اسکریپ کردن از قوانین سایت و شرایط استفاده پیروی کنید، از ارسال درخواست‌های بیش‌ازحد کوتاه‌مدت خودداری کنید و به rate-limit احترام بگذارید.

جمع‌بندی

استفاده از XPath همراه با Playwright در پایتون ترکیبی قدرتمند برای وب اسکریپینگ فراهم می‌کند: XPath دقت انتخاب را بالا می‌برد و Playwright مدیریت مرورگر، صبر داخلی و APIهای عملیاتی را فراهم می‌آورد. در عمل از XPathهای نسبی و مقاوم استفاده کنید، صبر (waiting) را درست تنظیم کنید، و عملیات استخراج را با مدیریت خطا و retry ترکیب کنید تا اسکریپ‌های پایدار و قابل نگهداری بسازید.

مقاله‌های مرتبط
اسکرپینگ با Selenium و Playwright
1404-11-20
اسکریپ با Playwright: گرفتن اسکرین‌شات
این راهنمای عملی نشان می‌دهد چگونه با Playwright انواع اسکرین‌شات (صفحه کامل، ناحیه‌ای، المنتی، سفارشی با کیفیت) بگیریم، خروجی را به بافر منتقل کنیم، PDF بسازیم و خطاهای رایج را رفع کنیم. مثال‌های کد محور، نکات بهینه‌سازی و الگوهای retry/pattern برای پروژه‌های وب اسکریپینگ ارائه شده‌اند.
اسکرپینگ با Selenium و Playwright
1404-11-18
اسکریپ فرم‌ها با Playwright برای توسعه‌دهنده‌های پایتون
این راهنمای عملی به توسعه‌دهنده‌های پایتون نشان می‌دهد چگونه با Playwright فرم‌های وب را برای اسکریپینگ و تست اتوماتیک کنند؛ شامل انتخابگرها، نمونه‌کدهای پایتون برای انواع ورودی‌ها، مدیریت پاسخ‌ها، روش‌های حل کپچا و نکات رفع اشکال و بهترین‌شیوه‌ها است.
اسکرپینگ با Selenium و Playwright
1404-11-17
مدیریت کوکی‌ها با Playwright
این مقاله یک راهنمای عملی برای مدیریت کوکی‌ها با Playwright در وب اسکریپینگ ارائه می‌دهد: گرفتن، فیلتر، ذخیره/بارگذاری، حذف و نکات تولیدی. مثال‌های پایتون، بهترین شیوه‌ها و روش‌های عیب‌یابی به شما کمک می‌کنند کوکی‌ها را امن و پایدار در خودکارسازی‌ها مدیریت کنید.