Playwright Python — справочникНа главный сайт

Что такое фреймы в Playwright?

Фреймы (iframe) — это встроенные HTML-документы внутри основной страницы. Playwright предоставляет удобные методы для работы с ними. Каждый Frame имеет собственную DOM-модель, доступную через те же локаторы, что и у Page.

Получение фрейма

Фрейм можно получить по CSS-селектору, имени или URL:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com")

    # По CSS-селектору (FrameLocator)
    frame_locator = page.frame_locator("iframe#content")

    # По имени
    frame = page.frame(name="main-frame")

    # По URL
    frame = page.frame(url="https://example.com/embedded")

FrameLocator — поиск внутри фрейма

page.frame_locator() возвращает FrameLocator, который позволяет искать элементы внутри iframe как в основной странице:

# Найти кнопку внутри iframe
frame = page.frame_locator("iframe#chat")
button = frame.get_by_role("button", name="Отправить")
button.click()

# Заполнить поле внутри фрейма
frame.locator("#message").fill("Привет!")

Прямой доступ к фрейму (Frame)

Методы page.frame() возвращают объект Frame, который поддерживает все те же методы, что и Page:

frame = page.frame(name="content")
frame.fill("#search", "query")
frame.get_by_text("Найти").click()
frame.wait_for_load_state("networkidle")

Выполнение JavaScript во фрейме

frame = page.frame(name="content")
title = frame.evaluate("() => document.title")
print(f"Заголовок фрейма: {title}")

Список всех фреймов на странице

for frame in page.frames:
    print(f"Имя: {frame.name}, URL: {frame.url}")

Вложенные фреймы (child_frames)

Фреймы могут содержать вложенные фреймы. Свойство frame.child_frames возвращает дочерние фреймы:

def print_frames(frame, indent=0):
    print(" " * indent + f"Frame: {frame.name} ({frame.url})")
    for child in frame.child_frames:
        print_frames(child, indent + 2)

print_frames(page)

Цепочка frame_locator для вложенных фреймов

Для глубоко вложенных iframe можно выстраивать цепочки:

# Внешний iframe -> внутренний iframe -> элемент
button = page.frame_locator("iframe#outer") \
             .frame_locator("iframe#inner") \
             .get_by_role("button", name="OK")
button.click()

Ожидание селектора во фрейме

frame = page.frame(name="content")
frame.wait_for_selector(".loaded", state="visible", timeout=10000)

Frame.content() и Frame.title()

frame = page.frame(name="main")
html = frame.content()
title = frame.title()
print(f"Заголовок: {title}")

События фреймов

Playwright генерирует события при добавлении, удалении и навигации фреймов:

def on_frame_attached(frame):
    print(f"Фрейм добавлен: {frame.url}")

def on_frame_detached(frame):
    print(f"Фрейм удалён: {frame.url}")

def on_frame_navigated(frame):
    print(f"Фрейм обновлён: {frame.url}")

page.on("frameattached", on_frame_attached)
page.on("framedetached", on_frame_detached)
page.on("framenavigated", on_frame_navigated)

Полный пример с фреймами

import re
from playwright.sync_api import sync_playwright

def test_iframe():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        page.goto("https://example.com/with-iframe")

        # Работа с iframe по селектору
        frame = page.frame_locator("iframe#payment")
        frame.get_by_placeholder("Номер карты").fill("4111111111111111")
        frame.get_by_placeholder("MM/YY").fill("12/28")
        frame.get_by_role("button", name="Оплатить").click()

        # Проверка основного фрейма
        main_frame = page.frame(name="main")
        assert main_frame.get_by_text("Оплата прошла").is_visible()

        browser.close()

test_iframe()
Совет: Используйте page.frame_locator() вместо frame(), когда фрейм может динамически загружаться — FrameLocator автоматически ожидает появления iframe.
Внимание: События frameattached и framedetached не срабатывают для основного фрейма страницы (page.main_frame). Используйте framenavigated для отслеживания навигации основного фрейма.