Урок 14. Selenium Работа с динамическими элементами
На многих современных сайтах элементы создаются динамически с помощью JavaScript. Это могут быть кнопки, формы, списки или уведомления, которые появляются не сразу после загрузки страницы. Чтобы корректно взаимодействовать с такими элементами, Selenium предоставляет инструменты явного ожидания.
Импорт и подготовка
Начнем с импорта необходимых модулей и открытия страницы с динамическими элементами:
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
import time
driver = webdriver.Chrome()
driver.get("https://example.com/dynamic-elements") # URL страницы
Явное ожидание появления элемента
Если элемент появляется с задержкой, использование time.sleep() неэффективно.
Лучше использовать WebDriverWait с условием expected_conditions:
wait = WebDriverWait(driver, 10) # Ждем до 10 секунд
try:
button = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "button.load-more"))
)
print("Элемент найден")
except:
print("Элемент не найден")
Клик по элементу после его появления
После того как элемент появится, можно безопасно выполнить по нему действие:
button.click()
print("Клик выполнен")
Использование других условий ожидания
Selenium предоставляет множество условий для динамических элементов:
visibility_of_element_located– элемент видим на странице.element_to_be_clickable– элемент кликабелен.text_to_be_present_in_element– проверка наличия текста в элементе.
# Пример ожидания, пока текст появится в элементе
wait.until(
EC.text_to_be_present_in_element((By.ID, "status"), "Готово")
)
Пример Плавной прокрутки страницы вниз и появление ранее не доступных данных
import time # Импорт модуля time для создания пауз между действиями
from selenium import webdriver # Основная библиотека Selenium для работы с браузером
from selenium.webdriver.common.by import By # Модуль для указания способов поиска элементов (By.CSS_SELECTOR, By.ID и т.д.)
from selenium.webdriver.chrome.service import Service # Класс для управления сервисом ChromeDriver
from selenium.webdriver.chrome.options import Options # Класс для настройки опций браузера Chrome
def smooth_scroll(driver, pause=0.3, step=300):
"""
Функция для плавной прокрутки страницы вниз в Selenium.
Эта функция реализует постепенную прокрутку, чтобы имитировать поведение реального пользователя.
Полезна для загрузки динамического контента и избежания обнаружения автоматизации.
:param driver: экземпляр webdriver - объект для управления браузером
:param pause: пауза между шагами прокрутки (в секундах), регулирует скорость движения
:param step: количество пикселей на шаг прокрутки, определяет гранулярность
"""
# Получаем полную высоту документа страницы через JavaScript
last_height = driver.execute_script("return document.body.scrollHeight")
pos = 0 # Начальная позиция прокрутки (верх страницы)
# Цикл продолжается, пока текущая позиция меньше полной высоты страницы
while pos < last_height:
pos += step # Увеличиваем позицию на шаг
# Выполняем JavaScript-команду для прокрутки к новой позиции (0 - по горизонтали, pos - по вертикали)
driver.execute_script(f"window.scrollTo(0, {pos});")
time.sleep(pause) # Пауза для плавности и загрузки контента
# Финальная прокрутка до самого низа страницы для гарантии полной загрузки
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
def main():
# URL сайта для тестирования - страница с примерами на parsertools.ru
url = "https://parsertools.ru/primers"
# Создание объекта опций для настройки браузера Chrome
options = Options()
# Аргумент для запуска браузера в максимально развернутом окне
options.add_argument("--start-maximized")
# Создание сервиса для ChromeDriver (предполагается, что он установлен в PATH)
service = Service()
# Инициализация драйвера Chrome с указанными опциями и сервисом
driver = webdriver.Chrome(service=service, options=options)
try:
# Загрузка начальной страницы сайта
driver.get(url)
# Пауза 2 секунды для полной загрузки контента и JavaScript-элементов
time.sleep(2)
# Бесконечный цикл для обработки всех страниц пагинации
while True:
# Шаг 1: Плавная прокрутка страницы до конца для загрузки всех элементов
smooth_scroll(driver, pause=0.3, step=300)
# Дополнительная пауза внизу страницы для завершения загрузки
time.sleep(2)
# Шаг 2: Поиск и определение номера текущей страницы по CSS-селектору
current_page = driver.find_element(By.CSS_SELECTOR, ".page-numbers.current").text
# Вывод информации о текущей странице в консоль для мониторинга
print(f"Сейчас на странице: {current_page}")
# Шаг 3: Поиск элементов кнопки "Следующая страница" (возвращает список)
next_button = driver.find_elements(By.CSS_SELECTOR, ".wp-block-query-pagination-next")
# Проверка наличия кнопки следующей страницы
if next_button:
# Вывод сообщения о переходе
print("Переход на следующую страницу...")
# Клик по первой найденной кнопке (индекс 0)
next_button[0].click()
# Пауза для загрузки новой страницы и её элементов
time.sleep(2)
else:
# Если кнопка отсутствует, это последняя страница - выход из цикла
print("Достигли последней страницы. Работа завершена.")
break
finally:
# Блок finally гарантирует закрытие браузера даже при ошибках
# Дополнительная пауза перед закрытием для просмотра результата
time.sleep(2)
# Закрытие экземпляра драйвера и освобождение ресурсов
driver.quit()
# Точка входа в программу - проверка, если скрипт запущен напрямую
if __name__ == "__main__":
main() # Вызов основной функции
Советы по работе с динамическими элементами
- Используйте явное ожидание вместо
time.sleep()для ускорения скриптов. - Если элементы обновляются через AJAX, проверяйте их состояние через условия из
expected_conditions. - Для сложных сценариев можно комбинировать ожидания нескольких элементов и условий.
Использование явных ожиданий позволяет Selenium корректно взаимодействовать с динамическими элементами и избегать ошибок, связанных с отсутствием элементов в DOM.
Больше уроков по парсингу на parsertools.ru/lessons.
