События (Events)

Playwright предоставляет богатую систему событий для отслеживания состояния страниц, контекстов и браузера.

События страницы

Подписка через page.on(event, handler).

request / response

def handle_request(req):
    print(f"Запрос: {req.method} {req.url}")

def handle_response(resp):
    print(f"Ответ: {resp.status} {resp.url}")

page.on("request", handle_request)
page.on("response", handle_response)
page.goto("https://example.com")

console

Перехватывает вызовы console.log, console.error, console.warn из браузера.

def on_console(msg):
    print(f"[{msg.type}] {msg.text}")

page.on("console", on_console)
page.evaluate("console.warn('Предупреждение!')")

dialog

Перехватывает alert, confirm, prompt.

def handle_dialog(dialog):
    print(f"Диалог: {dialog.message}")
    dialog.accept()

page.on("dialog", handle_dialog)
page.evaluate("alert('Привет!')")

popup

Срабатывает при открытии нового окна/вкладки.

def handle_popup(popup):
    popup.wait_for_load_state()
    print(f"Новое окно: {popup.url}")

page.on("popup", handle_popup)
page.evaluate("window.open('https://example.com')")

download

def handle_download(download):
    download.save_as("downloaded.pdf")
    print(f"Скачан: {download.suggested_filename}")

page.on("download", handle_download)
page.get_by_text("Скачать").click()

filechooser

def handle_filechooser(fc):
    fc.set_files("report.pdf")

page.on("filechooser", handle_filechooser)
page.get_by_text("Выбрать файл").click()

pageerror

Ловит необработанные JavaScript-ошибки.

def on_error(exc):
    print(f"JS ошибка: {exc}")

page.on("pageerror", on_error)

crash

Срабатывает при падении вкладки (about:crash).

def on_crash(page):
    print("Страница упала!")

page.on("crash", on_crash)

load / domcontentloaded

page.on("load", lambda: print("Загружено"))
page.on("domcontentloaded",
         lambda: print("DOM готов"))

События контекста

Новая страница в контексте

def on_new_page(page):
    print("Создана новая страница")

context.on("page", on_new_page)

Сетевые события контекста

context.on("request", handle_request)
context.on("response", handle_response)
context.on("requestfailed",
           lambda req: print(f"Провал: {req.url}"))
context.on("requestfinished",
           lambda req: print(f"Готов: {req.url}"))

События браузера

def on_disconnected(browser):
    print("Браузер отключён")

browser.on("disconnected", on_disconnected)

Управление обработчиками

Удаление обработчика

page.remove_listener("request", handle_request)

Одноразовый обработчик

page.once("dialog",
          lambda d: d.accept())

Ожидание событий (expect_event)

Метод expect_event ожидает событие и возвращает его объект. Используется как контекстный менеджер.

context.expect_event("page")

with context.expect_event("page") as page_info:
    page.click("a[target=_blank]")

new_page = page_info.value
print(new_page.title())

page.expect_event("download")

with page.expect_event("download") as dl_info:
    page.get_by_text("Экспорт").click()

download = dl_info.value
download.save_as("export.pdf")

page.expect_event("popup")

with page.expect_event("popup") as popup_info:
    page.get_by_text("Открыть в новом окне").click()

popup = popup_info.value
popup.wait_for_load_state()
Примечание: Контекстный менеджер гарантирует, что событие будет перехвачено, даже если оно произошло до вызова основной операции.

Полный пример сбора сетевых логов

import json
from playwright.sync_api import sync_playwright

logs = []

def on_request(req):
    logs.append({"type": "request",
                  "url": req.url,
                  "method": req.method})

def on_response(resp):
    logs.append({"type": "response",
                  "url": resp.url,
                  "status": resp.status})

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.on("request", on_request)
    page.on("response", on_response)
    page.goto("https://example.com")
    browser.close()

with "network_logs.json", "w" as f:
    json.dump(logs, f, indent=2)
Важно: Обработчики событий исполняются синхронно в основном потоке. Избегайте блокирующих операций внутри хендлеров.