Тема 6: Браузерная автоматизация: Selenium vs Playwright. Почему ты ненавидишь Селениум и чем Плейрайт круче?
Если httpx — это снайперская винтовка, то браузерная автоматизация — это танк. Громко, медленно, жрет много топлива, но проезжает там, где пехота ложится.
Но танки бывают разные. Есть Т-34 времен дедов (Selenium), а есть Абрамс с электроникой (Playwright).
1. Selenium — "Ржавое Ведро"
Давай честно. Selenium создавали для тестировщиков, чтобы проверять, работает ли кнопка "Купить". Его не делали для парсинга миллионов страниц.
- Архитектура (WebDriver): Это "Испорченный телефон".
- Твой код -> Драйвер (exe-файл) -> Браузер.
- Эта прослойка тормозит, глючит и падает.
- Главные грехи:
- Синхронность: Он блокирует поток. Запустил 10 браузеров — положил сервер.
- Flaky (Нестабильность): Самая частая ошибка —
ElementNotVisibleException. Ты ищешь кнопку, а она еще не дорендерилась. Приходится писать костыли:time.sleep(5)или громоздкиеWebDriverWait. - Детект: Сайты палят Selenium по одному щелчку пальцев (
navigator.webdriver = true). Нужно ставить патчи,undetected-chromedriver, танцевать с бубном. - Управление ресурсами: Один браузер = Один профиль. Хочешь 50 потоков с разными куками? У тебя сгорит оперативка, потому что ты запустишь 50 полных копий Хрома.
Вердикт: В 2026 году использовать Selenium для нового проекта — это мазохизм. Оставь его для поддержки легаси-кода 2015 года.
2. Playwright — "Киберпанк Имплант"
Microsoft посмотрела на страдания с Selenium/Puppeteer и сделала вещь.
- Архитектура: Работает через протокол CDP (Chrome DevTools Protocol) или его аналоги. Общается с браузером напрямую, "по венам".
- Киллер-фичи для парсинга:
- Контексты (Contexts) — ЭТО ГЛАВНОЕ.
- Ты запускаешь ОДИН инстанс браузера.
- Внутри него создаешь 100 изоллированных "Контекстов" (как инкогнито-вкладки).
- Каждый контекст имеет свои Cookies, свои Proxy, свой User-Agent.
- Итог: Экономия памяти в 10 раз. Скорость запуска — миллисекунды.
- Auto-Wait (Авто-ожидание):
- Ты пишешь
page.click('button'). Playwright САМ ждет, пока кнопка появится, перестанет быть прозрачной, перестанет двигаться и станет кликабельной. Никакихtime.sleep(). Скрипты становятся железными.
- Ты пишешь
- Перехват сети (Network Interception):
- Ты можешь запретить загрузку картинок (
.png,.jpg) и шрифтов одной строкой. Страница грузится в 5 раз быстрее. - Ты можешь перехватывать JSON-ответы от API прямо из браузера (гибридный парсинг).
- Ты можешь запретить загрузку картинок (
- Асинхронность:
async/awaitиз коробки.
- Контексты (Contexts) — ЭТО ГЛАВНОЕ.
⚔️ СРАВНЕНИЕ В ЦИФРАХ
| Фича | 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).
- Если сайт сложный (SPA, защиты) — ставь Playwright.
- Забудь Selenium как страшный сон. Единственное исключение — если ты попал на проект, где уже написано 100 тысяч строк кода на Selenium, и тебе платят, чтобы ты страдал.