AI Agents PRO: LangGraph, AutoGen и LLMOps в продакшнеИнструменты и интеграцииБраузерные агенты (Playwright)

Браузерные агенты (Playwright)

Уроки курсаБраузерные агенты (Playwright)

Изоляция: sandbox, контекст, download/upload

При автоматизации браузера с помощью Playwright тесты или действия агентов могут влиять друг на друга. Например:

  • Куки или локальное хранилище могут сохранять данные между запусками, вызывая неожиданные результаты.

  • Несколько тестов могут изменять состояние одной и той же страницы.

  • Скрипты одного агента могут «засорять» браузер или вкладки для других задач.

Представьте: вы тестируете процесс авторизации. Первый тест успешно логинится и сохраняет куки. Второй тест должен проверить поведение для незалогиненного пользователя, но браузер «помнит» сессию из первого теста, и проверка проваливается. Или два агента работают одновременно, и данные одного попадают в контекст другого.

Изоляция позволяет запускать каждый тест или действие в отдельной песочнице, чтобы изменения одного процесса не влияли на другие. Давайте разберёмся, как это работает в Playwright.

Контекст браузера (Browser Context) — изоляция сессий

Playwright поддерживает Browser Contexts — это отдельные окружения внутри одного браузера. Каждый контекст имеет свои куки, локальное хранилище, кэш и разрешения. Это похоже на режим инкогнито: когда вы закрываете окно, всё состояние стирается.

Важно понимать: контекст может содержать несколько страниц (вкладок), и все страницы внутри одного контекста разделяют состояние — куки, авторизацию, локальное хранилище. Если вам нужна полная изоляция между страницами, создавайте отдельные контексты.

Пример:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)  # чтобы видеть результат

    # Контекст для первого пользователя
    context1 = browser.new_context()
    page1 = context1.new_page()
    page1.goto("https://www.google.com")
    
    # Закрываем всплывающее окно (если оно есть — может не появиться у всех)
    # Проверяем наличие кнопки перед кликом
    if page1.locator("button:has-text('Не интересует')").count() > 0:
        page1.locator("button:has-text('Не интересует')").click()
    
    # Используем textarea для ввода запроса и нажимаем Enter
    page1.fill("textarea[name='q']", "Python")
    page1.press("textarea[name='q']", "Enter")
    print("User1 сделал поиск")
    context1.close()  # Очистка данных после использования

    # Повторяем для второго пользователя
    context2 = browser.new_context()
    page2 = context2.new_page()
    page2.goto("https://www.google.com")
    
    if page2.locator("button:has-text('Не интересует')").count() > 0:
        page2.locator("button:has-text('Не интересует')").click()
    
    page2.fill("textarea[name='q']", "Playwright")
    page2.press("textarea[name='q']", "Enter")
    print("User2 сделал поиск")
    context2.close()

    browser.close()  # Закрываем контексты и браузер

Примечание: Пример использует Google, но имейте в виду, что интерфейс и всплывающие окна могут различаться в зависимости от региона, языка или настроек аккаунта. Если код не работает у вас, попробуйте другой сайт или используйте проверку наличия элементов перед взаимодействием с ними.

Пояснения:

  • Каждый контекст имеет свои данные: куки, локальное хранилище, кэш, разрешения.

  • Закрытие контекста автоматически очищает все его данные и освобождает ресурсы — это основной способ «уборки».

  • Контексты полезны для параллельного тестирования нескольких пользователей или сценариев.

Песочница (Sandbox) — изоляция процессов

Контексты браузера дают изоляцию сессий (куки, storage), но не изолируют процессы на уровне операционной системы. Если вам нужна более глубокая изоляция — например, для запуска потенциально опасного кода или полной независимости задач — можно запускать несколько отдельных процессов браузера.

Песочница — это среда, в которой браузер или агент запускается полностью изолированно на уровне процессов:

browser1 = p.chromium.launch(headless=True)
browser2 = p.chromium.launch(headless=True)

Такой подход помогает избежать конфликтов между независимыми задачами и тестами на более глубоком уровне, чем просто контексты. Каждый процесс браузера полностью независим от других.

Анти-побочные эффекты

Анти-побочные эффекты — это методы и практики, которые минимизируют влияние одного действия на другое:

1. Закрытие контекста после использования

Это основной и рекомендуемый способ очистки. Закрытие контекста автоматически удаляет все куки, кэш, разрешения и освобождает ресурсы:

context = browser.new_context()
# ... работа с контекстом ...
context.close()  # всё очищено

В некоторых случаях может понадобиться частичная очистка без закрытия контекста:

  • context.clear_cookies() — очищает все куки, сохранённые в данном контексте.

  • context.clear_permissions() — очищает все разрешения, выданные сайту в этом контексте.

Но в большинстве случаев проще и надёжнее просто закрыть контекст и создать новый.

2. Отдельные страницы или контексты для действий

  • Не используйте одну страницу для разных сценариев.

  • Каждое действие или тест — новая вкладка или, лучше, новый контекст.

3. Фиксированные состояния

Перед тестом можно принудительно установить состояние страницы, например:

page.goto("https://example.com/reset")

Это гарантирует одинаковые условия для всех тестов.

Сохранение контекста — работа с сессиями

Мы говорили об очистке состояния, но иногда нужно обратное: сохранить состояние между запусками. Например, пройти авторизацию один раз и использовать её во всех последующих тестах. Это особенно полезно, когда авторизация требует двухфакторной аутентификации или занимает много времени.

В Playwright, как и в реальном браузере, это делается с помощью сессий и куки файлов.

Куки представляют собой небольшие фрагменты данных, которые веб-сервер отправляет браузеру. Эти данные могут включать идентификаторы сессий, настройки пользователя и другую информацию. В Playwright каждый контекст может работать со своими куками, и мы можем их добавлять программно:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context()

    # Добавление куки
    context.add_cookies([{
        'name': 'session_id',
        'value': '123456',
        'url': 'https://example.com'
    }])

    page = context.new_page()
    page.goto('https://example.com')

    # Получение куки
    cookies = context.cookies()
    print(cookies)

    browser.close()

Можно сохранять полное состояние контекста на диск и загружать его при следующем запуске. Это включает куки, локальное хранилище и другие данные сессии:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    
    # Создаём новый контекст
    context = browser.new_context()
    page = context.new_page()

    # Переходим на сайт
    page.goto("https://example.com/auth")

    # Вводим логин/пароль
    page.fill("input[name='username']", "my_username")
    page.fill("input[name='password']", "my_password")
    page.click("button[type='submit']")

    # Сохраняем состояние контекста на диск
    context.storage_state(path="state.json")
    print("Состояние пользователя сохранено!")

    browser.close()

Порой вместо ввода логина и пароля, прописывания кнопок быстрее просто руками авторизоваться. Можно открыть страницу авторизации и после этого поставить выполнение кода на паузу с помощью page.pause(). Далее можно заполнить все необходимые поля, нажать все необходимые кнопки, чебоксы и т.д. После чего в инспекторе нажать resume (или F8)

И потом загружаем это состояние, и наш сайт открывается в состоянии пройденной авторизации:

context = browser.new_context(storage_state="state.json")
page = context.new_page()
page.goto("https://example.com")  # сессия восстановлена

Файл state.json содержит куки и локальное хранилище, и это позволяет агенту "помнить" пользователя между тестами или запусками.

Загрузка и выгрузка файлов в Playwright

Автоматизация работы с файлами — загрузка документов на сайт и скачивание результатов — часто нужна для тестирования форм или сбора данных.

1. Загрузка файлов (download)

При клике на ссылку или кнопку браузер начинает скачивание файла. Чтобы корректно перехватить этот момент, используется контекст ожидания expect_download:

with page.expect_download() as download_info:
    page.click("text=Скачать файл")  # действие, которое инициирует загрузку

download = download_info.value      # объект скачанного файла
download.save_as("local_file.pdf")  # сохранение файла на диск

2. Выгрузка файлов (upload)

Для загрузки файлов на сайт используется метод set_input_files:

page.set_input_files("input[type=file]", "example_file.txt")

# Несколько файлов
page.set_input_files("input[type='file']", ["file1.txt", "file2.txt"])

Playwright напрямую подставляет файл в input[type=file], браузер «считает», что пользователь выбрал файл вручную. После этого можно нажимать кнопку отправки формы.

Важные моменты

  • expect_download используется только вместе с действием, запускающим скачивание

  • set_input_files работает без GUI-диалогов — не нужно взаимодействовать с системным окном выбора файлов

  • оба механизма не требуют таймаутов и sleep, так как встроены в систему ожиданий Playwright

Итоги

  • Изоляция обеспечивает независимость действий разных агентов и тестов, предотвращая побочные эффекты.

  • Контексты браузера дают изоляцию сессий (куки, storage, кэш), а отдельные процессы браузера — полную изоляцию на уровне ОС.

  • Закрытие контекста — основной способ очистки состояния; оно автоматически удаляет все данные и освобождает ресурсы.

  • Сохранение состояния контекста позволяет переиспользовать авторизацию и настройки между запусками.