مقدمه
در این مقاله به صورت عملی و جزئی به نحوهٔ یافتن عناصر HTML با استفاده از CSS Selectors در Selenium خواهیم پرداخت. فرض کنید یک توسعهدهندهٔ پایتون در سطح متوسط هستید که میخواهید اسکریپینگ (اسکریپینگ) پایدار و قابل نگهداری بنویسید؛ پس در پایان این مطلب شما میتوانید انواع سلکتورها را بنویسید، استراتژیهای انتظار را مدیریت کنید و خطاها را به صورت ایمن کنترل کنید.
آنچه یاد میگیرید:
- اصول CSS Selector و انواع آن
- یافتن یک یا چند عنصر با find_element و find_elements
- انتظارهای صریح و ضمنی و مدیریت عناصر دینامیک
- مثالهای پایتون با توضیح ورودیها، خروجیها و گامبهگام اجرا
مبانی CSS Selectors
CSS Selectorها روشهای قدرتمندی برای اشاره به عناصر DOM هستند. انواع رایج عبارتاند از: نام تگ، آیدی (#id), کلاس (.class), صفتها ([attr=value]), انتخابگرهای سلسلهمراتبی (descendant / child) و انتخابگرهای همتراز (sibling).
چند مثال ساده که در اسکریپها مفیدند:
- div → بر اساس تگ
- #main → بر اساس آیدی
- .btn.primary → بر اساس کلاسها
- input[name='q'] → بر اساس صفت
- div > p → فرزند مستقیم
یافتن یک عنصر با CSS Selector
برای گرفتن اولین عنصر مطابق از متد find_element استفاده میکنیم. ورودیها و خروجیهای اصلی:
- ورودیها: یک نمونهٔ درایور (مثلاً Chrome) و سلکتور رشتهای
- خروجی: یک شیء WebElement یا پرتاب NoSuchElementException در صورت عدم پیدا شدن
from selenium import webdriver
from selenium.webdriver.common.by import By
# باز کردن مرورگر
driver = webdriver.Chrome()
# پیمایش
driver.get('https://quotes.toscrape.com')
# پیدا کردن هدر اولیه
h1 = driver.find_element(By.CSS_SELECTOR, 'h1')
print('H1:', h1.text)
driver.quit()
توضیح کد: ابتدا یک درایور کروم میسازیم، آدرس را لود میکنیم، By.CSS_SELECTOR تعیین میکند که رشتهٔ بعدی CSS است و پس از بازگرداندن اولین عنصر، متن آن را چاپ میکنیم.
یافتن تمام عناصر مطابق
برای گرفتن همهٔ عناصر مطابق از find_elements استفاده کنید که همیشه لیستی برمیگرداند (اگر هیچ عنصری نیابد، لیست خالی برمیگردد). این روش برای جمعآوری لیستها مناسب است.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://quotes.toscrape.com')
# انتخاب تمام span ها با کلاس text
quotes = driver.find_elements(By.CSS_SELECTOR, "span.text")
for q in quotes:
print('Quote:', q.text)
driver.quit()
توضیح: نتیجهٔ find_elements یک لیست از WebElement است؛ در حلقه میتوانید هر کدام را استخراج و پردازش کنید.
انتظارها: مدیریت عناصر دینامیک
صفحات مدرن ممکن است عناصر را پس از بارگذاری اولیه اضافه یا تغییر دهند؛ استفاده از انتظارهای صریح (WebDriverWait + expected_conditions) بهترین روش برای تعامل امن است.
انتظار صریح برای حضور عنصر
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get('https://example.com')
# ورودی: driver و سلکتور، خروجی: WebElement پس از حاضر شدن در DOM
elem = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#menu-button'))
)
# اکنون میتوانیم با elem تعامل کنیم
print(elem.tag_name)
driver.quit()
توضیح: presence_of_element_located فقط از حضور در DOM اطمینان میدهد، نه قابل کلیک بودن؛ برای کلیک کردن از element_to_be_clickable یا ترکیب با ActionChains استفاده کنید.
انتظار ضمنی
انتظار ضمنی با driver.implicitly_wait(seconds) تنظیم میشود و برای تمام فراخوانیهای یافتن عنصر اعمال میگردد. ساده است اما کنترل کمتری نسبت به انتظار صریح ارائه میدهد.
مثال: کلیک امن با ActionChains
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get('https://example.com')
wait = WebDriverWait(driver, 10)
menu_btn = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#menu')))
actions = ActionChains(driver)
actions.move_to_element(menu_btn).click().perform()
# حالا صبر میکنیم تا منوی باز شده ظاهر شود
menu = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#menu-content')))
print(menu.text)
driver.quit()
گامها: پیدا کردن دکمه، حرکت موس و کلیک (برای رفع مشکلات قابل تعامل نبودن)، سپس انتظار تا محتوای منو قابل مشاهده شود.
استفاده از سلکتورهای صفتی (Attribute Selectors)
صفتها ابزار انعطافپذیری برای انتخاب عناصر فراهم میکنند:
- [attr] → وجود صفت
- [attr='val'] → مقدار مساوی
- [attr*='sub'] → حاوی
- [attr^='start'] → شروع با
- [attr$='end'] → پایان با
# مثال: انتخاب input هایی که name شامل 'user' است
inputs = driver.find_elements(By.CSS_SELECTOR, "input[name*='user']")
for i in inputs:
print(i.get_attribute('name'))
نکته عملی: استفاده از صفتها به جای کلاسهای تولید شدهٔ دینامیک (مثلاً کلاسهای حاوی هش) معمولاً پایدارتر است.
ترکیب سلکتورها و سلسلهمراتب
با ترکیب سلکتورها میتوانید بسیار دقیقتر هدفگیری کنید. مثالها:
- div input → همه inputهای داخل div (descendant)
- form > input → فقط فرزندان مستقیم
- label + input → input مجاور label
- ul li ~ p → همه p های همسطح بعد از li
# مثال ترکیب: input های متنی با کلاس form-control
fields = driver.find_elements(By.CSS_SELECTOR, "input[type='text'].form-control")
for f in fields:
print(f.get_attribute('id'))
رفع اشکال و روشهای متداول
وقتی عنصر پیدا نمیشود، ابتدا آن را در DevTools مرورگر با inspect بررسی کنید، سپس از ابزارهای زیر کمک بگیرید:
- کپی CSS selector از DevTools و آزمایش در Console با document.querySelector
- استفاده از انتظارهای صریح تا از زمانبندی صفحه مطمئن شوید
- در صورت لزوم از XPath به عنوان جایگزین استفاده کنید، اما XPath اغلب کندتر و پرخطاتر است
مدیریت خطا
برای پایایی، خطاها را هندل کنید، مخصوصاً در پروژههای اسکریپینگ طولانی مدت:
from selenium.common.exceptions import NoSuchElementException
try:
header = driver.find_element(By.CSS_SELECTOR, 'h6')
print(header.text)
except NoSuchElementException:
print('عنصر h6 یافت نشد')
finally:
driver.quit()
در این الگو: اگر عنصر وجود نداشت مرورگر بسته میشود و اسکریپ به صورت کنترلشده خاتمه مییابد.
بهترین روشها برای اسکریپینگ با CSS
- سعی کنید سلکتورهای معنادار و کوتاه بنویسید؛ از مسیرهای بسیار طولانی و شکننده پرهیز کنید.
- بین دقیق بودن و انعطافپذیری تعادل برقرار کنید: یک سلکتور خیلی خاص با کوچکترین تغییر صفحه میشکند.
- از صفتها و عناصر والد معنادار استفاده کنید تا شناخت ساختار صفحه سریعتر شود.
- بهینهسازی عملکرد: فقط عناصر لازم را انتخاب کنید و از حلقههای غیرضروری و عملیات سنگین درون حلقهها دوری کنید.
- امنیت و مسئولیتپذیری: قوانین سایت را بررسی کنید و ریت لیمیت، پراکسی و مدیریت کوکی/هدرها را رعایت کنید تا شانس بلاک شدن کاهش یابد.
جمعبندی
با یادگیری اصول CSS selectors، روشهای یافتن یک یا چند عنصر، و بکارگیری انتظارهای مناسب، میتوانید اسکریپینگ با Selenium را قابلاطمینانتر و پایدارتر کنید. از صفتها و ترکیب سلکتورها برای نوشتن انتخابگرهای منعطف استفاده کنید و همیشه خطاها و تغییرات DOM را در نظر بگیرید.
شروع کنید با چند صفحهٔ هدف و مجموعهای از تستهای کوچک تا سلکتورهای مناسب را پیدا کنید و آنها را در پروژهٔ واقعی به کار ببرید.





