📖 Теория: конспект локаторов Selenium (Урок 05)

🎯 Итоговое повторение

← К оглавлению урока

⚡ Краткий конспект локаторов

  • Локатор — способ однозначно определить элемент на странице. Используется через класс By.
  • DevTools: F12 → Elements → ПКМ → Copy selector / Copy XPath.
  • CSS: #id, .class, [name="val"], parent child, parent > child, [href*="фрагмент"].
  • XPath: //*[@id="..."], //tag[text()="..."], //tag[contains(@attr,"...")], //parent/child vs //parent//child.
  • find_element() → WebElement или NoSuchElementException.
  • find_elements() → list[WebElement] или [].
  • is_displayed() → True/False; .text → только видимый текст.

Что такое локатор веб-элемента

Локатор веб-элемента — это способ однозначно определить нужный элемент на веб-странице. Он используется для взаимодействия с HTML-элементами: кнопками, полями ввода, ссылками и другими тегами.

Аналогия: локатор — это адрес элемента. Так же, как почтовый адрес однозначно указывает на конкретный дом, хороший локатор однозначно указывает на конкретный HTML-элемент.

Как найти локатор в DevTools

Для определения локатора используйте инструменты разработчика браузера.

Как открыть DevTools

  • Правый клик по элементу → «Просмотреть код» (Inspect)
  • Или нажать F12 / Ctrl + Shift + I (Windows) / Cmd + Option + I (Mac)
  • Переключиться на вкладку Elements (Элементы)

Как быстро скопировать локатор

В панели Elements — правый клик по нужному тегу → Copy → выбрать:

  • «Copy selector» — получить CSS-селектор
  • «Copy XPath» — получить XPath
Автоматически скопированный XPath из DevTools часто хрупкий: он строится по абсолютному пути (/html/body/div[3]/div/form/input[1]). Любое изменение HTML-структуры сломает такой локатор. Пишите XPath вручную на основе стабильных атрибутов.

CSS-селекторы

CSS-селекторы считаются быстрыми и удобными. Рекомендуются для большинства задач автоматизации.

По ID

<!-- HTML -->
<input id="username" type="text">

<!-- CSS-селектор -->
#username

По атрибуту name

<!-- HTML -->
<input name="email" type="text">

<!-- CSS-селектор -->
[name="email"]

По классу

<!-- HTML -->
<button class="btn-primary">Login</button>

<!-- CSS-селектор -->
.btn-primary

По вложенности: прямой и любой потомок

<!-- HTML -->
<div class="container">
    <button>Купить</button>
</div>

<!-- CSS: любой button внутри .container (любая глубина) -->
.container button

<!-- CSS: только прямой потомок .container -->
.container > button
CSS > vs пробел: .card-body > p — только прямые дочерние p. .card-body p — все p на любой глубине.

По частичному совпадению атрибута

<!-- HTML -->
<a href="/products/view/123">Подробнее</a>

<!-- CSS-селектор: *= ищет подстроку в значении атрибута -->
a[href*="/products/view/"]

XPath

XPath — язык запросов для поиска элементов в иерархической HTML-структуре. Мощнее CSS: позволяет искать по тексту и перемещаться вверх по дереву DOM. Как правило, медленнее CSS-селекторов.

Основной синтаксис XPath

Синтаксис Смысл
//*[@id="val"]Любой элемент с id="val"
//tag[@attr="val"]Элемент tag с атрибутом attr="val"
//tag[text()="..."]Поиск по точному тексту
//tag[contains(@attr,"...")]Частичное совпадение атрибута
//parent/childТолько прямой потомок (один уровень)
//parent//childЛюбой потомок (любая глубина)

Примеры XPath (на базе suninjuly.github.io/cats.html)

<!-- По ID -->
//*[@id="bullet"]

<!-- По классу (может вернуть несколько!) -->
//*[@class="card-text"]

<!-- По атрибуту name -->
//p[@name="Vova"]

<!-- По тексту кнопки -->
//button[text()="View"]

<!-- По частичному совпадению атрибута src -->
//img[contains(@src, "serious_cat")]

<!-- Прямой потомок -->
//div[@class="btn-group"]/button

<!-- Любой потомок -->
//div[@class="card-body"]//button
CSS или XPath? По умолчанию — CSS. XPath — когда нужно найти по тексту, перейти к родителю или CSS не справляется с задачей.

Метод find_element()

Ищет первый элемент, соответствующий локатору. Возвращает объект WebElement. Если не найден — выбрасывает NoSuchElementException.

# test_locators.py
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("http://example.com")

# По ID
element = driver.find_element(By.ID, "login-button")

# По классу
element = driver.find_element(By.CLASS_NAME, "button-primary")

# По CSS-селектору
element = driver.find_element(By.CSS_SELECTOR, "div.container > p")

# По XPath
element = driver.find_element(By.XPATH, "//button[text()='Отправить']")

# По атрибуту name
element = driver.find_element(By.NAME, "username")

print(element.text)  # Читаем видимый текст
driver.quit()

Обработка NoSuchElementException

# test_exception.py
from selenium.common.exceptions import NoSuchElementException

try:
    element = driver.find_element(By.ID, "non-existent")
    print("Элемент найден")
except NoSuchElementException:
    print("Элемент не найден")

Свойство .text

Возвращает видимый текст внутри элемента. Скрытый текст (display: none, visibility: hidden) не считывается.

# test_text.py
header = driver.find_element(By.TAG_NAME, "h1")
print(header.text)  # Выведет текст заголовка h1

Метод is_displayed()

Проверяет, видим ли элемент пользователю. Возвращает True или False.

Когда is_displayed() возвращает False

  • Элемент скрыт через CSS: display: none или visibility: hidden
  • Элемент за пределами экрана: position: absolute; left: -9999px
  • Элемент полностью прозрачен: opacity: 0
  • Элемент удалён из DOM
  • Родительский элемент скрыт (наследуется)
# test_visibility.py
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("http://example.com")

element = driver.find_element(By.ID, "myElement")
if element.is_displayed():
    print("Элемент виден на странице")
else:
    print("Элемент скрыт")

driver.quit()
Важное отличие: find_element() найдёт элемент, даже если он скрыт. is_displayed() нужен, чтобы убедиться в видимости.

Метод find_elements()

Ищет все элементы по локатору. Не выбрасывает исключение — возвращает пустой список [].

Метод Если не найден Тип результата
find_element() Выбрасывает NoSuchElementException WebElement
find_elements() Возвращает пустой список [] list[WebElement]
# test_find_elements.py
cards = driver.find_elements(By.CSS_SELECTOR, ".col-sm-4")
print(f"Найдено карточек: {len(cards)}")

for card in cards:
    assert card.is_displayed(), f"Карточка скрыта: {card.text}"