مقدمه
در این مقاله عملی بهزبان فارسی میخواهیم نحوهٔ گرفتن اسکرینشات با Selenium را بهصورت جزئی و گامبهگام آموزش دهیم. هدف این راهنما این است که بعد از خواندن آن بتوانید:
- اسکرینشات از viewport، عنصر مشخص، ناحیهٔ نمایان و کل صفحه بگیرید،
- مسائل مربوط به مرورگرهای مختلف، رزولوشن و زمانبندی (waits) را مدیریت کنید،
- اسکرینشاتها را برای اعتبارسنجی بصری، مستندسازی و دیباگ استفاده و مدیریت کنید.
مخاطب این مطلب توسعهدهندهٔ پایتون با سطح متوسط است؛ مثالها در پایتون و نکات فنی همراه با توضیح خطبهخط عرضه میشوند.
روشهای اصلی گرفتن اسکرینشات
چهار متد پرکاربرد در Selenium برای گرفتن تصویر از صفحه یا عناصر وجود دارد. در ادامه هر روش را با کد و توضیح عملی میبینیم.
1) گرفتن تصویر از Current Viewport
ایده کلی: گرفتن عکس از ناحیهٔ قابلدید مرورگر همانطور که الان روی صفحه نمایش داده شده است.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# ورودی: آدرس صفحه
# خروجی: فایل PNG ذخیرهشده روی دیسک
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get('https://example.com')
# حفظ حالت فعلی viewport در فایل current_viewport.png
driver.save_screenshot('current_viewport.png')
driver.quit()توضیح خطبهخط: webdriver.Chrome(...) درایور کروم را میسازد؛ get صفحه را باز میکند؛ save_screenshot یک PNG از ناحیهٔ قابلدید میسازد و مینویسد؛ در پایان quit مرورگر را میبندد.
2) گرفتن تصویر از یک عنصر خاص
ایده کلی: برای دیباگ یا اعتبارسنجی بصری گاهی فقط یک عنصر اهمیت دارد؛ با این متد تنها آن DOM element را ذخیره میکنیم.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# ورودی: locator عنصر
# خروجی: فایل PNG حاوی رندر همان عنصر
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get('https://example.com')
# پیدا کردن عنصر (مثال: شناسه someId)
element = driver.find_element(By.ID, 'someId')
# ثبت تصویر تنها از آن عنصر
element.screenshot('element_screenshot.png')
driver.quit()توضیح نقشها: find_element عنصر را برمیگرداند؛ خروجی تابع (element) یک آبجکت WebElement است که متد screenshot روی آن اجرا و فقط بخشی از صفحه که عنصر را شامل میشود ذخیره میشود. این روش برای چک ظاهری کامپوننتها عالی است.
3) گرفتن Visible Area با get_screenshot_as_file
این متد مشابه save_screenshot است ولی گاهی نام متفاوت در رابطها دیده میشود؛ خروجی همان ناحیهٔ قابلدید است.
# مشابه مثالهای بالا
# driver.get('...')
# ذخیرهٔ تصویر ناحیهٔ قابلدید
driver.get_screenshot_as_file('visible_area.png')نکته: بعضی از bindingها متدها را با نامهای متفاوت ارائه میدهند؛ در پایتون معمولاً save_screenshot رایج است و get_screenshot_as_file معادل کار را انجام میدهد.
4) گرفتن Full Page (کل صفحه)
ایده کلی: رندر و ذخیرهٔ کل صفحه شامل بخشهای اسکرولشده. در عمل برای گرفتن full-page معمولاً از Geckodriver (Firefox) یا افزونه/ابزارهایی مثل Selenium-stealth یا ترکیب جاوااسکریپت استفاده میشود.
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from webdriver_manager.firefox import GeckoDriverManager
# ورودی: url
# خروجی: فایل PNG از کل صفحه (در صورت پشتیبانی درایور)
driver = webdriver.Firefox(service=Service(GeckoDriverManager().install()))
driver.get('https://example.com')
# اگر درایور از متد پشتیبانی کند
driver.save_full_page_screenshot('full_page.png')
driver.quit()ملاحظات: این متد ممکن است بسته به نسخهٔ Geckodriver یا Selenium متفاوت عمل کند. در غیر این صورت باید طول صفحه را با JS محاسبه و بخشبخش اسکرول و stitch کنید یا از ابزارهای ثالث استفاده کنید.
مدیریت تفاوتهای مرورگر
مرورگرهای مختلف رفتارهای متفاوتی در رندر، اندازهٔ پنجره، و پشتیبانی از متدها دارند. چند نکتهٔ عملی:
- درایور مناسب را همیشه با WebDriver manager نصب و بهروز نگهدارید.
- در حالت headless دقت کنید که بعضی CSSها یا فونتها متفاوت رندر شوند.
- رزولوشن پنجره را صریح تنظیم کنید تا تصاویر در محیطهای مختلف قابلمقایسه باشند.
# نمونهٔ مقداردهی Chrome با رزولوشن مشخص
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
options = webdriver.ChromeOptions()
options.add_argument('--window-size=1920,1080')
driver = webdriver.Chrome(options=options, service=Service(ChromeDriverManager().install()))در Firefox میتوانید مشابهاً با FirefoxOptions عرض و ارتفاع را تنظیم کنید. برای Edge از EdgeChromiumDriverManager استفاده کنید.
همگامسازی و waits برای محتوای داینامیک
برای عناصر داینامیک همیشه از waits استفاده کنید تا از گرفتن تصویرِ قبل از رندر جلوگیری شود.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# مثال: منتظر میمانیم عنصر با ID مشخص قابلدید شود
wait = WebDriverWait(driver, timeout=10)
elem = wait.until(EC.visibility_of_element_located((By.ID, 'dynamicElement')))
elem.screenshot('dynamic_content.png')توضیح: WebDriverWait تا حداکثر 10 ثانیه صبر میکند؛ اگر visibility_of_element_located برقرار شود، عنصر بازگردانده و تصویر گرفته میشود. این الگو مانع flakiness میشود.
مقایسه تصاویر و اعتبارسنجی بصری
برای تستهای بصری ساده میتوانید تصاویر را با Pillow و NumPy مقایسه کنید؛ نمونهٔ مینیمال زیر برای بررسی برابری دقیق است (بدون آستانهٔ تفاضل):
from PIL import Image
import numpy as np
def compare_images(image_path1, image_path2):
# ورودی: دو مسیر فایل تصویری
# خروجی: True اگر دقیقاً برابر باشند، در غیر این صورت False
img1 = Image.open(image_path1).convert('RGBA')
img2 = Image.open(image_path2).convert('RGBA')
np_img1 = np.array(img1)
np_img2 = np.array(img2)
if np_img1.shape != np_img2.shape:
return False
return np.array_equal(np_img1, np_img2)
نکتههای عملی: این مقایسه بسیار سختگیرانه است—کوچکترین پیکسل متفاوت را خطا میگیرد. برای کاربردهای واقعی از روشهای آستانهای (diff + SSIM) یا کتابخانههایی مثل imagehash یا ابزارهای بصری تست بهره ببرید.
بهترین شیوهها برای مدیریت اسکرینشاتها
- سازماندهی پوشهها: ساختار /screenshots/<feature>/<test_name>/ برای پیدا کردن سریع تصاویر.
- قواعد نامگذاری: شامل نام تست، مرحله و وضعیت (مثلاً failure) باشید:
login_test_step_1.png. - تایماستمپ: برای ردگیری زمانی از قالب ISO استفاده کنید:
2024-01-11_15-30-45_login.png. - ادغام با فریمورک تست: عکسها را درون fixtureها بگیرید تا بهصورت خودکار در گزارش ذخیره شوند.
# نمونهٔ سادهٔ pytest fixture برای ثبت اسکرینشات
import pytest
@pytest.fixture(autouse=True)
def capture_screenshot(request, driver):
# قبل از هر تست: میتوانیم یک تصویر شروع بگیریم
driver.save_screenshot(f"screenshots/{request.node.name}_start.png")
yield
# بعد از هر تست: نام فایل براساس نام تست ذخیره میشود
driver.save_screenshot(f"screenshots/{request.node.name}_end.png")
در این مثال فرض شده fixture به driver دسترسی دارد؛ در عمل driver را از fixture دیگری inject کنید.
مسائل رایج و راهحلها
- تصاویر خیلی بزرگ یا فضای ذخیره زیاد: از فشردهسازی یا پاکسازی قدیمیها استفاده کنید.
- عدم ثبات در headless: تنظیم رزولوشن و فونت سیستم را بررسی کنید یا از حالت headful استفاده کنید.
- خطاهای StaleElementReference هنگام گرفتن تصویر عنصر: قبل از گرفتن تصویر از عنصر، آن را مجدداً locate کنید.
- متد full-page کار نکرد: از اسکرول بخشبخش + stitch یا ابزارهای جانبی استفاده کنید.
نکات امنیتی و حقوقی
هنگام اسکریپ کردن و گرفتن اسکرینشات دقت کنید که محتوای خصوصی یا قابلاستناد را بدون مجوز ذخیره نکنید. همچنین هنگام ذخیره تصاویر حاوی دادههای حساس، دسترسی فایلها را محدود کنید و در گزارشها جزئیات حساس را فیلتر کنید.
جمعبندی
گرفتن اسکرینشات با Selenium یک ابزار ساده اما قدرتمند برای دیباگ، اعتبارسنجی بصری و مستندسازی است. استراتژی مؤثر شامل انتخاب روش مناسب (viewport، عنصر، visible یا full-page)، همگامسازی درست با waits، مدیریت تفاوتهای مرورگر و پیادهسازی قواعد ذخیرهسازی و نامگذاری است. با رعایت این نکات میتوانید تستها را پایدارتر کنید و فرآیند دیباگ را بسیار سریعتر سازید.
حالا میتوانید یکی از الگوها را انتخاب و در پروژهٔ خود پیاده کنید — و اگر نیاز به نمونهٔ کد سفارشی یا حل مشکل خاصی دارید، خوشحال میشوم کمک کنم.
آسان اسکریپ را در گوگل بهعنوان منبع ترجیحی انتخاب کن
مقالههای جدید ما زودتر و پررنگتر در نتایج گوگل و Discover برایت نمایش داده میشود. افزودن از تنظیمات گوگل





