humanemulator.net — справка. Продукт, демо и покупка — на хуманэмулятор.рф | Демо | Купить | API | лог изменений

Обновлено в августе 2026. · Руководство humanemulator.net

Ожидание, фреймы и SPA

Теги: браузер wait SPA iframe

navigate вернул управление — это не значит, что кнопка уже в DOM. На SPA форма рисуется после XHR, во iframe её не видно из корневого документа. Надёжный порядок: открыть → ждать конкретный элемент → кликать.

Ожидание элемента вместо фиксированной паузы
1NavigateURL открыт
2Waitexists по атрибуту
3Frame?номер или 0:1
4Действиеclick / set

Почему не sleep

Фиксированные sleep(3) либо мало (элемент ещё нет), либо много (робот тормозит на каждой странице). Сеть, кэш и SPA непредсказуемы: одна и та же форма на офисном канале появляется за 0,4 с, через прокси — за 8 с.

Sleep маскирует гонку: сегодня «повезло», завтра после релиза фронта — клик в пустоту. Wait привязан к факту: поле есть в DOM, текст «Готово» появился, спиннер пропал.

Короткая пауза после успешного wait («как человек») — нормально. Пауза вместо wait — нет.

Что именно ждать

Выберите один стабильный признак готовности и не меняйте его внутри сценария:

  • Поле формыname / id логина. Дальше заполнение: гайд по формам.
  • Текст — «Корзина», «Спасибо», заголовок шага wizard.
  • URL — если редирект после submit надёжнее DOM (осторожно: SPA часто не меняет path).
  • Исчезновение — спиннер/оверлей: сначала wait появления контента под ним, не «подождать 2 секунды».

Нестабильно: порядковый номер элемента, класс из CSS-модулей, динамический id вида react-aria-…. Их хватает на один прогон и ломает следующий релиз сайта.

wait и exists

Общие методы — в a_common. Две семьи:

  • wait_* — крутить проверку, пока элемент не появится или не кончится таймаут шаблона.
  • is_exist_* — один снимок «есть / нет», без ожидания. Удобно в ветке: капча всплыла или нет.

Wait по разным ключам (все на хабе a_common):

Разовая проверка: is_exist_by_name($name, $frame=-1).

$browser->navigate("https://example.com/app");
if ($browser->get_last_navigation_error()) {
  echo $browser->get_last_navigation_error();
}
$input->wait_element_exist_by_attribute("name", "login", true, -1);
if (!$input->is_exist_by_name("login")) {
  echo "поля логина нет — другой шаблон страницы";
}

Поиск: wait_element_exist.

Таймаут шаблона

Время ожидания задаётся переменной $iSecondsWaitElementExistBeforeAction (по умолчанию 15 секунд) в файле шаблона xweb_human_emulator для каждого языка. Не плодите разные sleep в каждом скрипте: один таймаут на проект, исключения — явно в комментарии.

15 секунд мало для тяжёлого кабинета за медленным прокси — поднимите в шаблоне. 15 секунд много для внутреннего стенда — уменьшите, чтобы падать быстрее на опечатке селектора.

Один таймаут на проект лучше десятка разных sleep. Если один шаг (оплата, выгрузка отчёта) объективно дольше — поднимите переменную перед ним и верните обратно, либо вынесите этот шаг в отдельный скрипт с своим шаблоном. Не копируйте «магические» 30 секунд в каждый файл «на всякий случай»: ночной робот просто станет медленным.

Элемент во iframe

Почти все DOM-методы принимают $frame = -1 (корень документа). Если поле внутри фрейма — передайте номер. Вложенные фреймы: строка "0:1" (первый фрейм страницы, внутри него второй). Объект frame — посчитать и найти сами фреймы.

// форма оплаты во втором фрейме корня
$input->wait_element_exist_by_name("card", 1);
// фрейм внутри фрейма
$input->wait_element_exist_by_name("cvv", "0:1");
Симптом «метод нашёл не то / не нашёл»: скрипт смотрит в корень, а форма в iframe платёжки, чата или старого frameset. Сначала найдите frame в инспекторе Studio (Ctrl + ПКМ), потом wait с этим номером.

Методы *_in_frame* и параметр $frame у обычных wait — один и тот же смысл: область поиска не корень.

SPA и «пустая» страница

navigate может завершиться по загрузке каркаса, пока данные ещё в полёте. Документ «готов», форма — нет.

  1. ключевое поле формы — как в гайде по формам;
  2. текст в контейнере: wait_element_exist_by_inner_text или by_inner_html;
  3. селектор CSS — get_by_query_selector.

get_last_navigation_error отвечает за HTTP/сеть (DNS, 404, обрыв), не за отрисовку React. Пустая ошибка навигации и пустой DOM одновременно — классика SPA: сеть ок, JS ещё рисует.

Спиннер: не sleep(2) после клика. Ждите появления текста результата или исчезновения оверлея через повторный is_exist в цикле с тем же таймаутом шаблона. Cookie-баннер и модалка логина часто перекрывают поле: сначала закройте их, потом wait формы.

Полный прогон: открыть → ждать → кликнуть

Минимальный каркас, который стоит копировать в новый скрипт вместо «navigate и сразу click»:

$browser->navigate("https://example.com/cabinet");
$err = $browser->get_last_navigation_error();
if ($err) {
  echo $err;
}
$input->wait_element_exist_by_attribute("name", "login", true, -1);
if (!$input->is_exist_by_name("login")) {
  echo "нет поля login — другой шаблон или iframe";
}
$input->set_value_by_name("login", "user");
$anchor->wait_element_exist_by_inner_text("Войти");
$anchor->click_by_inner_text("Войти");
$anchor->wait_element_exist_by_inner_text("Выход");

После wait заполнение полей — гайд по формам. Лог пишите после wait: logger.

Чеклист, если wait сорвался

  1. Инспектор: атрибут совпадает с тем, что в скрипте (регистр, пробелы).
  2. Элемент во frame? Смените $frame.
  3. Страница ещё на промежуточном URL (редирект логина).
  4. Оверлей/cookie-баннер перекрывает поле — сначала закрыть баннер.
  5. Таймаут шаблона меньше реальной загрузки.
  6. Не тот экземпляр Studio: порты.

Пишите в лог после wait, не до: logger. Иначе в журнале «страница готова», а клик уже упал.

FAQ

Wait всегда таймаутится. Селектор устарел или смотрите не тот frame. Сверьте в инспекторе, не в DevTools чужого Chrome.

Нашёл элемент, клик мимо. Элемент в DOM, но невидимый / нулевой размер / под модалкой. Wait проверяет наличие, не hit-test мыши. Иногда нужен click по видимому родителю.

XPath хрупкий? Да. Держите xpath запасным вариантом после name/attribute.

Wait нашёл элемент, is_exist сразу false. Страница перерисовалась (SPA), элемент с тем же name появился заново. После wait ещё раз проверьте exists перед click.

Фрейм «прыгает». Реклама и чат добавляют iframe; номер 1 сегодня — платёжка, завтра — виджет. Ищите frame по содержимому через объект frame, не зашивайте номер навсегда без комментария.

Связанные сбои: хаб ошибок, навигация.

Все руководства · С чего начать · Поиск API