Selenium 4: автоматизация браузера

Selenium управляет настоящим браузером так, будто за ним сидит человек.
Selenium — инструмент автоматизации браузера. В версии 4 он сам скачивает драйвер (Selenium Manager), умеет находить элементы по CSS/XPath и дожидаться их появления. Его исходно создавали для тестирования, но он отлично подходит и для скрейпинга динамики.

Selenium запускает Chrome или Firefox и даёт API: открыть URL, кликнуть, ввести текст, прокрутить, забрать HTML. В Selenium 4 больше не нужно вручную качать ChromeDriver — встроенный Selenium Manager делает это сам. Установка:

pip install selenium

Минимальный скрейпер на Selenium 4 (запускать у себя, в браузерном раннере его нет):

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless=new')   # без окна

driver = webdriver.Chrome(options=options)
try:
    driver.get('https://quotes.toscrape.com/js/')
    quotes = driver.find_elements(By.CSS_SELECTOR, '.quote .text')
    for q in quotes:
        print(q.text)
finally:
    driver.quit()   # обязательно закрыть браузер

Явные ожидания вместо sleep

Главная боль динамики — данные появляются не мгновенно. Наивный time.sleep(5) либо тормозит, либо не дожидается. Правильный путь — явные ожидания: ждать конкретного условия.

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

wait = WebDriverWait(driver, 10)
# ждём, пока появится хотя бы одна цитата
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.quote')))

Как работает под капотом

Selenium общается с браузером по протоколу WebDriver: твои команды («кликни», «найди элемент») превращаются в HTTP-запросы к локальному драйверу, который дёргает браузер. WebDriverWait в цикле опрашивает условие раз в доли секунды, пока оно не станет истинным или не истечёт таймаут. Это устойчивее фиксированной паузы: как только данные появились — выполнение продолжается, не теряя ни лишней секунды, ни нужного элемента.

Имитация действий пользователя

Сила Selenium в том, что он умеет всё то же, что человек в браузере: кликать кнопки, заполнять формы, прокручивать страницу, переключать вкладки. Это открывает доступ к данным, спрятанным за взаимодействием — например, к контенту, который подгружается только при скролле (бесконечная лента) или после нажатия «Показать ещё». Через element.click(), element.send_keys() и выполнение JS (driver.execute_script) скрейпер воспроизводит сценарий, после которого нужные данные появляются в DOM.

Но за гибкость платят ресурсами и хрупкостью. Каждый браузер — это десятки мегабайт памяти и заметное время старта; запускать их пачками тяжело. Селекторы в динамике ещё капризнее, чем в статике, потому что элементы появляются и исчезают. Поэтому в Selenium особенно важны явные ожидания и аккуратное закрытие драйвера. Частый удобный приём — довести страницу до нужного состояния через Selenium, забрать driver.page_source и дальше разбирать привычным BeautifulSoup: так ты совмещаешь силу браузера с удобством зрелого парсера.

Частые ошибки

  • Забыть driver.quit(). Незакрытые браузеры висят в памяти и плодят процессы.
  • Использовать time.sleep вместо ожиданий. Это хрупко и медленно — бери WebDriverWait.
  • Не включать headless на сервере. Без графической среды браузер с окном просто не стартует.

Best practices

  • Оборачивай работу в try/finally с driver.quit().
  • Используй явные ожидания (WebDriverWait + expected_conditions).
  • Забрав driver.page_source, парси его привычным BeautifulSoup — это часто удобнее, чем API Selenium.

Для запуска на сервере без графической оболочки незаменим headless-режим, а вместе с ним — управление окном и паузами. Полезно задавать размер окна (--window-size), потому что отзывчивая вёрстка на узком экране может прятать элементы, и отключать загрузку картинок ради скорости, если они не нужны. Эти мелкие настройки превращают Selenium из «работает на моём ноутбуке» в инструмент, стабильно крутящийся в облаке или контейнере — что и требуется для регулярного сбора данных.

Итог: Selenium 4 поднимает реальный браузер и сам управляет драйвером. Ключ к надёжности — явные ожидания вместо sleep и обязательное quit() в finally.

Проверьте себя
1. Чем явное ожидание (WebDriverWait) лучше time.sleep при скрейпинге динамики?
AОно красивее выглядит
BОно продолжает работу сразу, как условие выполнено, и не теряет элемент при медленной загрузке
Ctime.sleep запрещён в Python
DМежду ними нет разницы
2. Почему важно вызывать driver.quit() (обычно в блоке finally)?
AЧтобы сохранить данные
BЧтобы закрыть браузер и не оставлять висящие процессы, поедающие память
CЭто ускоряет интернет
Dquit() не обязателен