Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 5 из 25 ~18 мин +50 XP

Клик и ввод текста

Управление страницей начинается там, где чтение заканчивается: chromedp click нажимает настоящие кнопки, а chromedp sendkeys печатает в поля — событиями мыши и клавиатуры, а не подменой HTML. Разберём механику клика и ввода, когда SetValue честнее SendKeys и почему после клика программа должна ждать так же дисциплинированно, как после Navigate.

Содержание урока · 10 разделов

Каталог прочитан, селекторы настроены — и тут задача вырастает: найти товар по названию. Для этого нужно напечатать запрос в строку поиска, нажать кнопку и дождаться результатов. Это уже не парсинг, а управление: программа ведёт себя как пользователь, и сайт отвечает ей как пользователю. Именно на этом шаге у новичков ломается интуиция, потому что у управления страницей есть два соблазнительных, но неправильных пути — отредактировать DOM напрямую или понадеяться, что «клик есть клик». Оба пути работают до первого сайта с валидацией, живыми обработчиками и фреймворком, который хранит состояние отдельно от разметки. В этом уроке — механика честного управления: как chromedp click отправляет настоящие события мыши, как chromedp sendkeys синтезирует клавиатуру, когда SetValue уместнее обоих и что происходит с ожиданиями после нажатия кнопки, если за ней прячется переход.

chromedp click: настоящие события мыши#

chromedp.Click работает не как вызов JavaScript-метода click(), а как рука пользователя: браузеру отправляются события мыши — нажатие и отпускание кнопки — по координатам найденного узла. Разница не академическая. Настоящие события мыши всплывают по дереву, будят обработчики наведения, активируют фокус и запускают всю цепочку реакций, которую сайт повесил на кнопку; программный click() через JS часто срабатывает только на самом узле и минует часть этой цепочки. Чтобы координаты вообще существовали, Click внутри себя дожидается видимости узла — условие NodeVisible добавляется к действию по умолчанию, — а невидимый элемент браузер при необходимости прокручивает в поле зрения: перед кликом выполняется ScrollIntoViewIfNeeded, поэтому элемент, оказавшийся ниже границы экрана, дотянется до видимой области сам. Из механики следуют два практических правила. Первое: кликать можно только видимое — если элемент спрятан под оверлеем загрузки или в неоткрытой вкладке, клик не дойдёт. Второе: клик идёт по первому узлу результата — селектор должен однозначно указывать на кнопку, а не на коллекцию из десяти подходящих элементов. Для двойных кликов и других жестов есть отдельные действия, о них ниже.

Поиск: напечатать, нажать, дождаться

GO
err := chromedp.Run(ctx,
        chromedp.SendKeys("#search", "меховые тапочки", chromedp.NodeVisible),
        chromedp.Click("button[type=submit]", chromedp.NodeVisible),
        chromedp.WaitVisible("#results"),
)

SendKeys дожидается видимого поля, фокусирует его и печатает запрос посимвольно; Click ждёт кнопку и шлёт события мыши по её координатам; WaitVisible дожидается блока результатов. Опция NodeVisible здесь показана явно для наглядности, хотя и Click, и SendKeys добавляют её по умолчанию — с невидимым узлом оба отказываются работать. Программа нигде не спит: на каждом шаге она ждёт факт, а не время.

chromedp sendkeys: клавиатура по буквам#

chromedp.SendKeys синтезирует клавиатуру: для каждого символа строки браузеру уходят события нажатия, ввода символа и отпускания клавиши — тот же поток, что идёт от настоящей клавиатуры. Перед вводом chromedp фокусирует поле. Строка передаётся целиком, включая управляющие символы: Enter, стрелки и забой едут тем же посимвольным конвейером, отдельное действие для них не нужно; событие ввода символа синтезируется только для печатных знаков, остальные уходят как чистые нажатия клавиш. Из этой механики следует главное свойство SendKeys, о котором ломаются половины скриптов: действие не очищает поле. Печать идёт в текущее значение — как у человека, который добавляет слова в уже набранный текст. Если в поле что-то было, вы получите склейку. Отсюда же и достоинство: для сайтов, которые валидируют каждый символ, показывают подсказки по мере ввода или включают кнопку только после «настоящего» набора, SendKeys — единственный способ пройти их корректно. Особый случай — загрузка файлов: если селектор указывает на input типа file, chromedp не печатает путь, а заполняет поле загрузки по-настоящему, через отдельный механизм браузера. Про формы целиком — валидации, дропдауны, чекбоксы — будет отдельный урок про формы, здесь фундамент.

SetValue: значение без клавиатуры#

Второй способ положить значение в поле — chromedp.SetValue: он ставит свойство value напрямую через JavaScript и затем возбуждает события input и change, чтобы фреймворки заметили изменение. Это быстрее посимвольного набора и гарантированно чистит поле: значение присваивается, а не допечатывается. Для десятков полей в формах экономия ощутимая. Но у скорости есть граница, и важно понимать, где она проходит: SetValue возбуждает события изменения, но не события клавиатуры — keydown и keyup не происходят, потому что клавиатуры не было. Для подавляющего большинства полей этого хватает: их состояние живёт на событиях input или change, и фреймворк видит значение — React и Vue слушают именно input, поэтому их состояние обновляется, и SetValue остаётся полноценным вводом для современных витрин, а не грязным хаком. Но если сайт повесил логику именно на нажатия клавиш — маски ввода, фильтрация символов, подсчёт по keyup —SetValue обойдёт эту логику стороной, и поле будет заполнено, а сайт о нём не узнает. Правило выбора звучит так: SetValue — когда нужно просто положить значение и сайт слушает изменения; SendKeys — когда важно само поведение набора. Спорные случаи решаются проверкой результата через чтение значения обратно.

Clear перед SendKeys: цикл без склеек

GO
// сайт валидирует по клавиатуре: SetValue обойдёт проверку,
// поэтому чистим и печатаем по-настоящему
err := chromedp.Run(ctx,
        chromedp.Clear("#search", chromedp.ByID),
        chromedp.SendKeys("#search", "меховые тапочки", chromedp.ByID),
        chromedp.Click("button[type=submit]"),
)

Clear обнуляет значение input или textarea, затем SendKeys печатает запрос в чистое поле, и только после этого идёт клик. Порядок важен: сначала уборка, потом набор. Clear работает через DOM и клавиатурных событий не шлёт, поэтому посимвольную валидацию не задевает — сайт проверяет значение, а не способ его очистки.

Четыре инструмента управления полями#

ДействиеМеханикаКогда брать
chromedp.Clickсобытия мыши по координатам узла, ждёт видимостикнопки, ссылки, чекбоксы, вкладки — всё, что нажимается
chromedp.SendKeysсобытия клавиатуры посимвольно, поле фокусируетсявалидация по набору, подсказки, Enter в поле поиска
chromedp.SetValueприсваивание value через JS плюс события input и changeциклы и большие формы: быстро, чистит поле
chromedp.Clearобнуление значения input или textareaперед SendKeys в переиспользуемых полях

После клика: навигация и гонки#

Кнопка редко бывает концом сценария: за ней открывается страница результатов, вкладка, модальное окно. И здесь управление встречается с материалом прошлого урока — ожиданиями, потому что после Click начинается самая интересная гонка. События клика ушли, сайт начал реагировать: где-то поехал переход, где-то подтянулись результаты, и всё это занимает неопределённое время. Если следующее действие — чтение результатов — запустить сразу, оно попадёт в старую страницу и упадёт или прочитает мусор. Хорошая новость: chromedp сам закрывает большую часть дыры — Query-действия переспрашивают документ, и WaitVisible на целевом узле дожидается его появления, пусть даже после перехода. Остаток дисциплины — за вами: цель ожидания должна быть узлом новой страницы, а не чем-то, что совпадает и там, и там; заголовок старой страницы виден и до клика, ожидание пройдёт мгновенно и не докажет ничего. Поэтому в цепочках ждут уникальный для результата элемент: блок результатов, кнопку выхода из профиля, номер страницы. Отдельный случай — кнопка, которая отправляет форму синхронно: страница перезагружается целиком, и все ожидания начинаются заново, как после Navigate, — механика та же, поэтому и приём не меняется. Тонкие случаи, когда узлов два и оба «правильные», — территория умных ожиданий.

Двойной клик, Submit и другие жесты#

Одиночный клик — база, но не вся геометрия действий. DoubleClick посылает двойное нажатие той же механикой и нужен для интерфейсов, где одиночный клик выделения, а двойной открывает: файловые списки, таблицы с редактированием. chromedp.Submit отправляет родительскую форму найденного элемента — это замена нажатия Enter в поле: полезно, когда кнопка отправки не имеет устойчивого селектора, а форма одна. Для загрузки файлов существует SetUploadFiles — он принимает список путей и заполняет поле input типа file напрямую; SendKeys на таком поле тоже сработает, но явное действие читается лучше. Остальная геометрия — наведение, зажатие кнопки, перетаскивание — уже территория низкоуровневых событий мыши с координатами, и до неё дотягиваются в редких задачах; в курсе она не понадобится вплоть до итогового проекта. Все жесты, как и одиночный клик, применяются к первому узлу результата и добавляют NodeVisible по умолчанию: правила одной механики действуют без исключений, и селектор по-прежнему половина дела. Если сценарий разросся до десятков жестов, честный вопрос — не «какой ещё вызов добавить», а «не проще ли найти API», о котором говорили в первом уроке.

Порядок работы с формой#

  • дождаться видимости формы или первого поля — WaitVisible по селектору контейнера
  • для каждого поля: SetValue с заменой значения либо Clear плюс SendKeys
  • кликать по кнопке с однозначным селектором или отправлять форму через Submit
  • после отправки дождаться узла нового состояния — результатов, профиля, сообщения об ошибке
  • прочитать значение обратно через Value, если важна гарантия, что сайт увидел ввод
  • ошибки валидации на странице проверять явно — они тоже узлы DOM

Оговорка про песочницу, последняя в этом блоке уроков: управление страницей — это процессы и сеть, поэтому практиковаться нужно локально, с установленным Go и Chrome; интерактивы сайта проверяют механику и порядок действий, а тематическая программа на чистом Go в песочнице показывает поиск узлов без браузера. Кстати, для статических сайтов без скриптов всё то же самое — формы и POST-запросы — умеет делать Colly напрямую: смежный курс разбирает этот путь без браузера, и когда он сработает, он дешевле. А сессии после логина, куки и заголовки — тема тринадцатого урока.

Проверка: механика клика

Что делает chromedp.Click перед отправкой клика?

Проверка: что увидит сайт

Сайт валидирует поле на событии keydown. Какое действие пройдёт валидацию?

Что окажется в поле

Прочитайте код и выберите, что он выведет:

// <input id="q" value="страница">
// err := chromedp.Run(ctx, chromedp.SendKeys("#q", "поиск", chromedp.ByID))
// var v string
// err = chromedp.Value("#q", &v, chromedp.ByID)

Соберите вход по логину

Восстановите действия: печать логина и пароля, нажатие кнопки, ожидание профиля.

err := chromedp.Run(ctx, chromedp.("#login", "ivan", chromedp.ByID), chromedp.("#pass", "qwerty", chromedp.ByID), chromedp.("button[type=submit]", chromedp.NodeVisible), chromedp.("#profile"), )

Расставьте сценарий поиска

Соберите по порядку программу: контекст, ввод запроса, клик и ожидание результатов.

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: управление страницей

Термин

chromedp.Click

нажмите, чтобы перевернуть
Определение

Настоящие события мыши по координатам узла: ждёт NodeVisible, прокручивает элемент в поле зрения, будит обработчики. Клик идёт по первому узлу результата.

1 / 6

Что дальше: управление и извлечение — две половины браузерного парсера. В шестом уроке — извлечение текста и атрибутов: Text, InnerHTML и атрибуты узлов, из которых складываются данные. Девятый урок про умные ожидания закроет оставшиеся дыры между кликом и результатом. А когда база соберётся, двенадцатый урок доведёт формы до конца — заполнение и отправка со всеми сложными полями, от чекбоксов до загрузки файлов.

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

Коротко: что запомнить

  • Click шлёт настоящие события мыши по координатам узла: ждёт видимости, прокручивает элемент, будит всю цепочку обработчиков.
  • SendKeys синтезирует клавиатуру посимвольно и не очищает поле — переиспользуемые поля требуют Clear или SetValue.
  • SetValue ставит value через JS и возбуждает input с change: быстро и чисто, но события клавиатуры не происходят.
  • Сайты, валидирующие по keydown и keyup, проходят только SendKeys; поля, слушающие input, довольствуются SetValue.
  • Value читает значение обратно — ввод превращается в проверяемую операцию, а не в надежду.
  • После клика ждут узел нового состояния, уникальный для результата: заголовок старой страницы ожидание не докажет.
  • Клик идёт по первому узлу результата и требует видимости: селектор — половина успеха, как и в чтении данных.
  • DoubleClick, Submit и SetUploadFiles закрывают редкие жесты той же механикой: первый узел результата и требование видимости.

Домашнее задание

Возьмите селекторы из домашнего задания четвёртого урока и соберите сценарий: ввод запроса в поиск каталога, клик по кнопке, ожидание первого результата и чтение его названия. Затем реализуйте тот же ввод двумя способами — SendKeys и SetValue — и сравните поведение на сайте: где появились подсказки, где сработала валидация, что показало обратное чтение через Value. Повторите сценарий в цикле на три запроса и убедитесь, что поле чистится — например, парой Clear плюс SendKeys.

Личные заметкиПусто
Хранятся только в вашем браузере (Chromedp · Клик и ввод текста)

Вопросы и ответы по уроку

Почему Click не работает по кнопке, которая видна в браузере?

Частые причины: над кнопкой стоит оверлей — спиннер или баннер куков перехватывает события; элемент видимый, но селектор указывает на другой узел с тем же классом; кнопка активируется только после заполнения соседних полей. Проверка — дождаться исчезновения оверлея через WaitNotPresent и убедиться, что селектор в консоли находит именно кнопку. Если ничего не помогает, включите видимое окно: глазами сразу видно, что именно перехватывает клик.

SendKeys или SetValue — что выбрать для форм?

По умолчанию SetValue: быстрее, чистит поле, возбуждает input и change, которых хватает большинству фреймворков. SendKeys нужен там, где важен процесс набора: маски, посимвольная валидация, подсказки, кнопка, активирующаяся только от клавиатуры. Спорное поле решается обратным чтением значения и одним прогоном.

Как нажать Enter в поле поиска?

Передайте его символом в строке SendKeys — управляющий символ пойдёт как нажатие клавиши. Альтернатива — chromedp.Submit на элементе формы: он отправляет родительскую форму напрямую. После любого из вариантов дожидайтесь узла результатов, как после обычного клика. Для полей с автодополнением Enter иногда выбирает подсказку вместо отправки — проверьте на своём сайте, что именно отправляет форму.

Термины урока

Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.

Следующая ступень учебного пути

Testcontainers25 уроков~8 чпрактика25 уроков уже доступны

Testcontainers в Go: интеграционные тесты с Docker

Курс testcontainers-go: Postgres, Redis, Kafka и Mongo в тестах через Docker, wait-стратегии, сети, параллельность, CI и итоговый стенд. 25 уроков.

  • Поднимать реальные зависимости в Docker из кода теста
  • Использовать модули Postgres, Redis, MongoDB, Kafka и RabbitMQ
  • Ждать готовность сервиса wait-стратегиями вместо sleep
  • Собирать стенды из нескольких контейнеров и своего образа