Перейти к содержанию

Тема 6: Браузерная автоматизация: Selenium vs Playwright. Почему ты ненавидишь Селениум и чем Плейрайт круче?

Если httpx — это снайперская винтовка, то браузерная автоматизация — это танк. Громко, медленно, жрет много топлива, но проезжает там, где пехота ложится.

Но танки бывают разные. Есть Т-34 времен дедов (Selenium), а есть Абрамс с электроникой (Playwright).


1. Selenium — "Ржавое Ведро"

Давай честно. Selenium создавали для тестировщиков, чтобы проверять, работает ли кнопка "Купить". Его не делали для парсинга миллионов страниц.

  • Архитектура (WebDriver): Это "Испорченный телефон".
    • Твой код -> Драйвер (exe-файл) -> Браузер.
    • Эта прослойка тормозит, глючит и падает.
  • Главные грехи:
    1. Синхронность: Он блокирует поток. Запустил 10 браузеров — положил сервер.
    2. Flaky (Нестабильность): Самая частая ошибка — ElementNotVisibleException. Ты ищешь кнопку, а она еще не дорендерилась. Приходится писать костыли: time.sleep(5) или громоздкие WebDriverWait.
    3. Детект: Сайты палят Selenium по одному щелчку пальцев (navigator.webdriver = true). Нужно ставить патчи, undetected-chromedriver, танцевать с бубном.
    4. Управление ресурсами: Один браузер = Один профиль. Хочешь 50 потоков с разными куками? У тебя сгорит оперативка, потому что ты запустишь 50 полных копий Хрома.

Вердикт: В 2026 году использовать Selenium для нового проекта — это мазохизм. Оставь его для поддержки легаси-кода 2015 года.


2. Playwright — "Киберпанк Имплант"

Microsoft посмотрела на страдания с Selenium/Puppeteer и сделала вещь.

  • Архитектура: Работает через протокол CDP (Chrome DevTools Protocol) или его аналоги. Общается с браузером напрямую, "по венам".
  • Киллер-фичи для парсинга:
    1. Контексты (Contexts) — ЭТО ГЛАВНОЕ.
      • Ты запускаешь ОДИН инстанс браузера.
      • Внутри него создаешь 100 изоллированных "Контекстов" (как инкогнито-вкладки).
      • Каждый контекст имеет свои Cookies, свои Proxy, свой User-Agent.
      • Итог: Экономия памяти в 10 раз. Скорость запуска — миллисекунды.
    2. Auto-Wait (Авто-ожидание):
      • Ты пишешь page.click('button'). Playwright САМ ждет, пока кнопка появится, перестанет быть прозрачной, перестанет двигаться и станет кликабельной. Никаких time.sleep(). Скрипты становятся железными.
    3. Перехват сети (Network Interception):
      • Ты можешь запретить загрузку картинок (.png, .jpg) и шрифтов одной строкой. Страница грузится в 5 раз быстрее.
      • Ты можешь перехватывать JSON-ответы от API прямо из браузера (гибридный парсинг).
    4. Асинхронность: async/await из коробки.

⚔️ СРАВНЕНИЕ В ЦИФРАХ

Фича Selenium Playwright
Ожидание элементов Ручное (Больно) Автоматическое (Магия)
Изоляция сессий Новое окно браузера (Тяжело) Browser Context (Легко)
Блокировка рекламы/картинок Через костыли прокси Нативно, одной строкой
Генерация кода Нет playwright codegen (Запишет твои клики)
Поддержка языков Все Python, JS, C#, Java

👨‍💻 КОД: Почувствуй боль и наслаждение

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

driver = webdriver.Chrome() # Запуск тяжелого процесса
driver.get("<https://site.com>")

# Рукопашный бой с ожиданием
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
    element.click()
finally:
    driver.quit()

Playwright (Как делают сеньоры)

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        # Запускаем браузер 1 раз
        browser = await p.chromium.launch(headless=True)

        # Создаем легкий контекст (можно задать прокси тут)
        context = await browser.new_context(user_agent="Mozilla/5.0...")

        page = await context.new_page()

        # Блокируем картинки для скорости
        await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())

        await page.goto("<https://site.com>")

        # Он сам подождет появления кнопки!
        await page.click("#myDynamicElement")

        # Можно даже перехватить ответ API
        # async with page.expect_response("**/api/data") as response:
        #     data = await response.value.json()

        await browser.close()

asyncio.run(main())

🧠 Вывод Архитектора:

  1. Если сайт простой — не юзай браузер вообще (см. Блок 1).
  2. Если сайт сложный (SPA, защиты) — ставь Playwright.
  3. Забудь Selenium как страшный сон. Единственное исключение — если ты попал на проект, где уже написано 100 тысяч строк кода на Selenium, и тебе платят, чтобы ты страдал.