2025, Oct 05 11:16
Два надежных способа выбрать одно значение во всех select в Playwright (Python)
Как в Playwright для Python установить одно значение во всех select: два проверенных подхода, ожидание через wait_for, без ошибок итерации и тайминга.
Установить одинаковое значение сразу для нескольких HTML‑элементов select кажется простой задачей, но на практике она легко превращается в головную боль из‑за несоответствий API или проблем с таймингом. Если вы работаете с синхронным API Playwright для Python и хотите переключить все выпадающие списки на странице на один и тот же вариант, вот как сделать это без неприятных сюрпризов.
Воспроизводим проблему
Страница содержит несколько элементов select, например:
<select class="sc-fzXfMv sc-fzXfMw dRuVWn">
  <option value="json">JSON</option>
  <option value="text">Text</option>
  <option value="raw">Hex</option>
</select>
Первые попытки перебрать элементы и проставить нужный вариант приводили к ошибкам — от отсутствующих атрибутов до неитерируемых локаторов:
# Попытка 1
pg.locator("select").all()    # AttributeError: объект 'Locator' не имеет атрибута 'all'
# Попытка 2
pg.query_selector_all("select")    # AttributeError: объект 'Page' не имеет атрибута 'query_selector_all'
# Попытка 3
for ddl in pg.locator("select"):
    ddl.select_option("raw")        # TypeError: объект 'Locator' не является итерируемым
# Попытка 4
sels = pg.locator("select")
for s in sels:
    s.select_option("raw")          # та же ошибка: не итерируется
Что на самом деле происходит
Суть проблемы двойная. Во‑первых, Locator — это не объект, по которому можно напрямую итерироваться: он представляет запрос, способный соответствовать нескольким элементам, но сам по себе не является итерируемым. Во‑вторых, критичен тайминг. Если select‑элементы ещё не присутствуют в DOM или не видны, действия, требующие их наличия или интерактивности, будут падать. Поэтому важно либо заранее получить конкретный список элементов, либо подождать нужного состояния, прежде чем разворачивать локатор в список.
Два рабочих подхода
Первый вариант — получить конкретный список элементов select и пройтись по нему циклом. Для этого используем query_selector_all и выбираем нужный вариант для каждого элемента:
dropdown_nodes = pg.query_selector_all("select")
for node in dropdown_nodes:
    node.select_option("raw")
Альтернатива — остаться на локаторах и преобразовать их в список только после ожидания. Ожидание гарантирует, что элементы готовы к взаимодействию до начала обхода. Ниже показано использование wait_for, а затем all:
menus = pg.locator("select")
menus.first.wait_for(state="attached")
for item in menus.all():
    item.select_option("raw")
Иногда удобнее опереться на предикат ожидания по умолчанию — visible. В этой вариации мы ждём, пока первый подходящий select станет видимым, и лишь затем перечисляем все элементы:
lists = pg.locator("select")
lists.first.wait_for()
for dd in lists.all():
    dd.select_option("raw")
Если причина сбоев — в том, что элементы ещё не видны, именно шаг ожидания делает сценарий надёжным.
Почему это важно
Синхронный API Playwright предоставляет мощные механизмы автоожиданий, но важно выбирать корректный уровень абстракции. Итерироваться по Locator напрямую не получится, а попытка выполнить выбор до готовности DOM оборачивается лишними ошибками. Либо перечисляйте конкретные узлы через query_selector_all, либо дождитесь состояния локатора и затем используйте all — так код остаётся явным и устойчивым. Если совпадает несколько элементов, ожидание через first в связке с wait_for помогает избежать проблем в строгих сценариях.
Вывод и практические рекомендации
Когда требуется задать одинаковое значение для нескольких select‑элементов, держитесь одного из двух безопасных шаблонов. Либо возьмите список элементов через query_selector_all и пройдитесь по нему, либо подождите нужного состояния локатора и только потом разверните его через all перед итерацией. Если страница наполняется асинхронно, добавьте wait_for перед перечислением и, при необходимости, полагайтесь на предикат visible по умолчанию, чтобы убедиться, что элементы готовы к взаимодействию. Эти подходы делают код компактным, предсказуемым и согласованным с задумкой Playwright.