---
title: "Клик и ввод текста"
description: "chromedp click и chromedp sendkeys на Go: события мыши и клавиатуры, SetValue против SendKeys, Clear и гонка после клика — управление страницей с разбором."
course: "Chromedp в Go: автоматизация Chrome без Selenium"
url: "https://golangmaster.ru/courses/chromedp/lessons/05-klik-vvod/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 18
---

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

*Курс «Chromedp в Go: автоматизация Chrome без Selenium», урок 5 из 25. ~18 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/chromedp/lessons/05-klik-vvod/*

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

Каталог прочитан, селекторы настроены — и тут задача вырастает: найти товар по названию. Для этого нужно напечатать запрос в строку поиска, нажать кнопку и дождаться результатов. Это уже не парсинг, а управление: программа ведёт себя как пользователь, и сайт отвечает ей как пользователю. Именно на этом шаге у новичков ломается интуиция, потому что у управления страницей есть два соблазнительных, но неправильных пути — отредактировать 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 не печатает путь, а заполняет поле загрузки по-настоящему, через отдельный механизм браузера. Про формы целиком — валидации, дропдауны, чекбоксы — будет отдельный урок про [формы](/courses/chromedp/lessons/12-formy/), здесь фундамент.

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

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

> **Живое место: телевизортелевизор.** Классическая авария: парсер ходит по карточкам в цикле и печатает запрос в одно и то же поле поиска. SendKeys не чистит поле, и на второй итерации в строке лежит «телевизортелевизор» — поиск молча возвращает ноль результатов, программа честно пишет «товаров нет». Сломалась переиспользуемая сессия: значение из прошлого прогона никто не стёр. Лечение — Clear перед SendKeys или SetValue, который заменяет значение целиком. Спорное мнение с условием: SetValue быстрее и надёжнее для циклов, но если сайт валидирует по клавиатуре — остаётся пара Clear плюс 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, — механика та же, поэтому и приём не меняется. Тонкие случаи, когда узлов два и оба «правильные», — территория [умных ожиданий](/courses/chromedp/lessons/09-ozhidaniya-elementov/).

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

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

> **Проверяйте результат, а не надейтесь.** После SetValue и SendKeys не поленитесь прочитать значение обратно — chromedp.Value кладёт текущее value поля в строку. Это превращает ввод в проверяемую операцию: значение совпало — идём дальше, нет — программа узнаёт об этом сразу, а не после десяти минут пустого обхода. Тот же принцип применяется и к кликам: после нажатия дождитесь узла, который существует только в новом состоянии. Пара чтение-проверка дешевле часа отладки.

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

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

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

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

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

- Вызывает JavaScript-метод click() на узле
- ✅ Дожидается видимости узла и шлёт события мыши по его координатам
- Редактирует DOM, подставляя обработчик клика
- Ничего — клик отправляется сразу

Click добавляет условие NodeVisible и отправляет настоящие события мыши — нажатие и отпускание — по координатам узла, прокручивая его в поле зрения при необходимости. Поэтому клик будит те же обработчики, что и рука пользователя.

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

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

- SetValue — он возбуждает input и change
- ✅ SendKeys — он синтезирует настоящие события клавиатуры
- Оба одинаково — keydown приходит всегда
- Ни одно — нужен программный submit

SetValue ставит значение через JS и возбуждает события input и change, но события клавиатуры не происходят. SendKeys печатает посимвольно с keydown, вводом и keyup — только он проходит валидацию, завязанную на нажатия клавиш.

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

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

**Что выведет программа?**

- ✅ страницапоиск — SendKeys допечатал к существующему значению
- поиск — поле автоматически очистилось перед вводом
- страница — ввод не прошёл без Clear
- Ошибка: Value нельзя вызывать после SendKeys

SendKeys не очищает поле: печать идёт в текущее значение, как у человека в уже набранном тексте. Чистая замена — SetValue либо Clear перед SendKeys. Value здесь честно показал склейку — поэтому обратное чтение и полезно.

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

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

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

Подсказка: Текст в поля печатает SendKeys, кнопку нажимает Click, новое состояние дожидается WaitVisible.

Правильные ответы в пропусках: `SendKeys`, `SendKeys`, `Click`, `WaitVisible`

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

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

Правильный порядок строк:

1. `ctx, cancel := chromedp.NewContext(context.Background())`
2. `defer cancel()`
3. `err := chromedp.Run(ctx,`
4. `  chromedp.SendKeys("#search", "меховые тапочки", chromedp.NodeVisible),`
5. `  chromedp.Click("button[type=submit]", chromedp.NodeVisible),`
6. `  chromedp.WaitVisible("#results"),`
7. `)`

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

- **chromedp.Click** — Настоящие события мыши по координатам узла: ждёт NodeVisible, прокручивает элемент в поле зрения, будит обработчики. Клик идёт по первому узлу результата.
- **chromedp.SendKeys** — Синтез клавиатуры: keydown, ввод символа, keyup — посимвольно в сфокусированное поле. Не очищает значение; для input типа file заполняет путь загрузки.
- **chromedp.SetValue** — Присваивает value через JS и возбуждает события input и change. Быстро и чистит поле, но события клавиатуры не шлёт.
- **chromedp.Clear** — Обнуляет значение input или textarea. Обязателен перед SendKeys в переиспользуемых полях — иначе получится склейка значений.
- **chromedp.Value** — Читает текущее value поля в строку. Способ проверить, что ввод дошёл и сайт его увидел.
- **chromedp.Submit** — Отправляет родительскую форму найденного элемента — замена нажатию Enter, когда у кнопки отправки нет устойчивого селектора.

Что дальше: управление и извлечение — две половины браузерного парсера. В шестом уроке — [извлечение текста и атрибутов](/courses/chromedp/lessons/06-izvlechenie-teksta/): Text, InnerHTML и атрибуты узлов, из которых складываются данные. Девятый урок про [умные ожидания](/courses/chromedp/lessons/09-ozhidaniya-elementov/) закроет оставшиеся дыры между кликом и результатом. А когда база соберётся, двенадцатый урок доведёт формы до конца — [заполнение и отправка](/courses/chromedp/lessons/12-formy/) со всеми сложными полями, от чекбоксов до загрузки файлов.

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

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

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

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

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

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

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

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

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

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

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