Содержание урока · 10 разделов
Пятый урок дал базовые жесты: Click, SendKeys, SetValue, Clear. Отдельное поле он научил заполнять, но форма — это не пять полей по отдельности, а контракт: поля связаны валидацией, кнопка зависит от их состояния, а отправка запускает переход или XHR. Здесь у новичков собирается урожай странностей: SetValue на чекбоксе не включает галочку, Submit не вызывает обработчик формы, форма в цикле отправляется дважды, файл не грузится из-за пути. Всё это не баги библиотеки, а следствия механики, которую стоит разложить по полочкам один раз. В этом уроке — целая форма: какое действие выбрать для какого типа поля, как грузятся файлы, чем отличаются три способа отправки и как собрать цикл автозаполнения по сотне однотипных форм, чтобы он не падал на пятьдесят седьмой. База из пятого урока предполагается: механика SetValue с событиями input и change и правило «SendKeys не чистит поле» здесь используются, а не разбираются заново.
chromedp формы: карта действий по типам полей#
chromedp формы собирают из четырёх действий, и выбор определяется типом поля, а не вкусом. SetValue — рабочая лошадка для текстовых полей: логины, пароли, телефоны, даты без масок. Он ставит свойство value, возбуждает input и change, чистит поле сам и стоит куда меньше посимвольного набора. SendKeys остаётся для полей, где важен процесс набора: маски, посимвольная валидация, поля с подсказками, а также для Enter в поиске. Click обслуживает всё нажимаемое: кнопки, чекбоксы, радиокнопки, ссылки-переключатели — состояние переключателей через value не выставишь, там правит клик. SetUploadFiles — отдельное действие для input типа file, о нём ниже. Отправка — Click по кнопке, Submit или Enter, и разница между ними станет главной темой второй половины урока. Общий порядок не меняется с пятого урока: сначала WaitVisible на форму, потом действия по полям, потом отправка и ожидание узла нового состояния. Проверка результата через чтение Value тоже остаётся дешёвой страховкой: поле, которое сайт увидел, читается обратно с тем значением, что вы положили.
Логин целиком: от ожидания до профиля
GOerr := chromedp.Run(ctx,
chromedp.WaitVisible("#login-form"),
chromedp.SetValue("#email", "ivan@example.com"),
chromedp.SetValue("#password", "qwerty"),
chromedp.Click("button[type=submit]"),
chromedp.WaitVisible("#profile"),
)WaitVisible дожидается формы, SetValue ставит значения с событиями input и change, которых хватает React и Vue, Click нажимает кнопку с настоящими событиями мыши, WaitVisible доказывает переход в личный кабинет. Ни одного Sleep: каждый шаг ждёт факт. Если сайт валидирует по клавиатуре, поля вместо SetValue берут Clear плюс SendKeys из пятого урока.
Селекты, чекбоксы и радиокнопки#
Три типа полей требуют внимания, потому что работают не так, как текстовые. Селект — самый дружелюбный: SetValue на нём ставит свойство value, и если среди опций есть такая, браузер её выбирает; события input и change уходят, фреймворк замечает выбор. Главное — совпадение значения: value опции не всегда равен её тексту, «Москва» может лежать в value как msk, поэтому значение подсматривают в разметке, а не копируют с экрана. Если совпадение не нашлось, выбор делают кликом: Click по селекту, Click по опции — медленнее, но честнее для сайтов с кастомными дропдаунами, где под видом селекта живёт собственный компонент из div-ов. Чекбокс — полная противоположность: его состояние живёт в свойстве checked, а value — это просто строка, которая уедет на сервер. SetValue на чекбоксе меняет value, дёргает события, но галочку не ставит — типичная ловушка, разбор ниже в интерактиве. Работает Click по самому инпуту или по связанному label. Радиокнопки — те же чекбоксы с общим именем: клик по элементу нужного варианта, второй клик по соседней кнопке группы переключает выбор. Проверка состояния читается Evaluate-выражением по checked — это чтение, а не подмена. Отдельно держите в голове нативные поля с типом date или number: их value живёт в служебном формате — дата как yyyy-mm-dd — и SetValue ждёт именно его, а не локализованное отображение, которое видит человек на экране.
Поле → действие#
| Тип поля | Действие | Нюанс |
|---|---|---|
| text, email, password | SetValue | ставит value и возбуждает input с change |
| поле с маской и подсказками | Clear плюс SendKeys | процесс набора важнее скорости |
| select | SetValue по value опции | значение подсматривают в разметке; кастомный дропдаун — Click |
| checkbox, radio | Click по инпуту или label | состояние живёт в checked, а не в value |
| input типа file | SetUploadFiles | пути к файлам, не клики по диалогу |
| textarea | SetValue или SendKeys | перенос строк — символ в строке |
Файловые инпуты: SetUploadFiles#
Загрузка файла — поле, которое ломает интуицию сильнее остальных: клик открывает системный диалог, которым программа управлять не умеет, и на этом многие останавливаются. Останавливаться не нужно: диалог обходит сам браузер. chromedp.SetUploadFiles принимает селектор поля и список путей, отправляет браузеру команду dom.SetFileInputFiles, и файлы оказываются в поле так, будто их выбрал человек. Тот же путь внутри библиотеки срабатывает, если послать в поле SendKeys со строкой-путём: для input типа file клавиатурная механика отключается и печатание маршрутизируется в установку файлов, — но явное действие читается в коде лучше. Список путей важен: поле с атрибутом multiple принимает несколько файлов за раз, и они приходят одним вызовом. Два ограничения. Пути — это файловая система машины, где запущен Chrome: для локальной разработки это ваш компьютер, в Docker — контейнер, и отладка «файл не грузится» начинается с проверки, что путь существует именно там. И после установки файлов сайту положено событие, на котором он подхватит выбор; если фреймворк почему-то не среагировал, доталкивают Evaluate с dispatchEvent — та же механика событий, что и в обычных полях.
Отчёт в поле загрузки — и проверка
GOvar files int
err := chromedp.Run(ctx,
chromedp.WaitVisible("#doc"),
chromedp.SetUploadFiles("#doc", []string{"/tmp/report.csv"}),
chromedp.Evaluate(
"document.querySelector('#doc').files.length",
&files,
),
)
fmt.Println("файлов в поле:", files)SetUploadFiles отправляет путь в dom.SetFileInputFiles для первого узла по селектору; приёмник Evaluate получает количество файлов, которые браузер реально положил в поле. Если путь не существует или поле не файловое, счётчик честно покажет ноль — обратное чтение превращает загрузку в проверяемую операцию, как Value для текстовых полей.
Классическая авария: на форме обязательные поля и JS-обработчик, который валидирует и шлёт данные XHR-ом. Программа вызывает chromedp.Submit — и форма «отправляется», но ничего не происходит: обработчик не запустился, пустые обязательные поля не пожаловались. Причина в механике: Submit вызывает метод form.submit() самой формы, а по правилам платформы он не возбуждает событие submit и пропускает HTML5-валидацию — форма уходит напрямую. Живой обработчик стоит на событии, которого не было. Спорное мнение с условием: Submit полезен, когда нужна именно сырая отправка без скриптов; во всех остальных случаях честнее Click по кнопке — тот же маршрут, что у пользователя, со всей валидацией и обработчиками.
Enter, Submit и кнопка: три способа отправки#
Отправить форму можно тремя путями, и между ними реальная разница, а не вкусовщина. Click по кнопке type=submit — самый честный: браузер возбуждает событие submit, запускает JS-обработчики, прогоняет HTML5-валидацию с подсказками у невалидных полей, и только потом уезжает запрос или переход. Enter в поле — SendKeys со строкой \r, у клавиатурного пакета для неё есть константа kb.Enter: механика та же, что у нажатия кнопки, если форма считает Enter отправкой, но на многостраничных формах Enter иногда нажимает другую кнопку — проверяйте на своём сайте. Submit — сырой метод form.submit(): в обход событий и валидации, как разобрано в живом месте выше. После любого способа начинается новый круг ожиданий, знакомый по пятому уроку: переход перезагружает страницу, XHR — нет, и в обоих случаях дожидаются узла, который существует только в новом состоянии. В цикле по однотипным страницам держите один способ отправки на весь обход: на странице бывает несколько кнопок с type=submit — для вкладок, фильтров, отзывов, — и селектор по типу выберет первую попавшуюся; привязывайте клик селектором контейнера конкретной формы, а не общим типом кнопки. Ошибки валидации — тоже узлы: блок с сообщением у поля, красная рамка, счётчик :invalid. Их читают теми же Text и Evaluate, и именно это отличает устойчивый сценарий от надёжного: надёжный после отправки не просто ждёт success, а умеет увидеть ошибку и принести её в лог.
Прежде чем искать причину в коде парсера, прочитайте форму: chromedp.Text по селектору сообщения или Evaluate с document.querySelectorAll(':invalid').length покажет, что сайт отверг ввод и по какой причине. Одна строка чтения ошибки экономит час сравнения значений по полям. Тот же приём закрывает капчи-невидимки и пороги: сайт молча не сабмитит, но честно пишет причину в DOM.
Автозаполнение go-программой: цикл по формам#
Автозаполнение go-программой в промышленном виде — это цикл: строки данных на входе, формы на сайте, отчёт об ошибках на выходе. Скелет простой: на каждую строку — свежее ожидание формы, SetValue по полям, Click по кнопке, предикат на результат. Три детали отделяют работающий цикл от падающего. Первая: поля очищайте сами — SetValue перезаписывает, SendKeys допечатывает, и на второй итерации склейка гарантирует мусор. Вторая: падение одной формы не должно ронять обход — ошибка логируется с идентификатором строки, цикл идёт дальше, а сводка собирается в конце; ретраи и устойчивость здесь — территория пятнадцатого урока. Третья: если полей десятки, SetValue на каждое — это десятки обменов на форму; ускорение — один Evaluate с выражением, которое раскладывает значения по полям и дёргает события, — механика десятого урока. Отдельная честная оговорка: в старых статьях встречается действие SetSubmissionValues, будто бы заполняющее форму из карты одним вызовом — в текущей библиотеке его нет, массовое заполнение собирается циклом SetValue или JS-выражением. Готовые каталоги без JS-форм — территория Colly: смежный курс отправляет POST напрямую, когда браузер избыточен.
Порядок работы с формой#
- WaitVisible по селектору формы или контейнера полей
- текстовые поля — SetValue; маски и подсказки — Clear плюс SendKeys
- селект — SetValue по value опции; чекбоксы и радио — Click
- файлы — SetUploadFiles списком путей, затем проверка files.length
- отправка — Click по кнопке; Submit только для сырой отправки без обработчиков
- после отправки — WaitVisible на узел нового состояния и чтение ошибок валидации
- в цикле — ошибка формы логируется с идентификатором строки, обход продолжается
Проверка: Submit и required
На форме обязательное поле пустое, программа вызывает chromedp.Submit. Что произойдёт?
Проверка: чем заполнять селект
У селекта есть опция с value="msk" и текстом «Москва». Как её выбрать?
Что увидит сайт после SetValue на чекбоксе
Прочитайте код и выберите, что он выведет:
// <input type="checkbox" id="agree">
// err := chromedp.Run(ctx,
// chromedp.SetValue("#agree", "on"),
// )
// после этого сайт читает checked чекбоксаСоберите загрузку отчёта
Восстановите действия: значение поля, файл и отправка кнопкой.
Расставьте сценарий загрузки файла
Соберите по порядку: контекст, ожидание формы, поле, файл, проверка и отправка.
Строки
Ваша программа
Нажимайте на строки слева, чтобы собрать программу
Карточки: формы от полей до отправки
Что дальше: форма редко бывает первой страницей обхода — обычно за логином нужна сессия. Тринадцатый урок заберёт её целиком: заголовки, куки и сессии — как не логиниться на каждом шаге и чем cookies отличаются от заголовков авторизации. Если же форма стоит на странице с подгружаемыми списками, девятый урок про ожидания закроет гонки между заполнением и рендером. Практика — локально: понадобится установленный Go и Chrome, песочница сайта исполняет тематическую программу на чистом Go без браузера. Домашняя проверка на честность: возьмите форму с обязательными полями, отправьте её Submit с пустыми полями и посмотрите, уехала ли она, — ответ на этот вопрос дороже любого примера из урока.
Песочница урока
Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.
Запустите код, чтобы увидеть вывод.
Коротко: что запомнить
- Форма собирается из четырёх действий: SetValue для текста, SendKeys для набора, Click для переключателей, SetUploadFiles для файлов.
- SetValue на select выбирает опцию по совпавшему value; текст опции и её value — разные строки.
- Чекбоксы и радиокнопки переключаются Click: их состояние в checked, а SetValue трогает только value.
- SetUploadFiles кладёт список путей в поле через dom.SetFileInputFiles; проверка — files.length через Evaluate.
- Submit вызывает form.submit(): событие submit не срабатывает, HTML5-валидация пропускается.
- Click по кнопке — честный маршрут отправки с обработчиками и валидацией; Enter — SendKeys со строкой \r.
- Ошибки валидации — узлы DOM: читайте их, прежде чем искать причину в парсере.
- В цикле автозаполнения поля чистят сами, падение формы логируется, а обход продолжается.
Домашнее задание
Возьмите сайт с формой из трёх-пяти полей, обязательным полем и загрузкой файла, и соберите сценарий: ожидание формы, заполнение по типам полей из таблицы, загрузка файла с проверкой files.length, отправка кнопкой и чтение результата. Затем продублируйте отправку через Submit на форме с пустыми обязательными полями и сравните поведение с Click. Финал — цикл на три строки данных с заполнением одной и той же формы и логом ошибок по каждой строке; в лог добавьте время заполнения формы, чтобы видеть цену SetValue против Clear плюс SendKeys на своих полях.
Личные заметкиПусто
Вопросы и ответы по уроку
SetValue сработал, но сайт поле не увидел. Что проверить первым?
Обратное чтение через Value: если в поле лежит ваше значение, проблема в событиях — сайт слушает что-то ещё. SetValue возбуждает input и change, но не события клавиатуры; маски и посимвольная валидация требуют Clear плюс SendKeys. Если же в поле пусто, проверьте селектор: у страниц с вкладками часто два элемента с одинаковым id в разных скрытых блоках. Отдельный случай — дата и число: value хранится в служебном формате, и «01.03.2025» сайту не подходит, хотя экран показывает именно его.
Файл не грузится, ошибок нет. Где искать?
Проверьте три вещи: существует ли путь на машине, где запущен Chrome, — в Docker это файловая система контейнера; то ли это поле — селектор должен указывать на input типа file; и что сайт принял выбор — files.length через Evaluate покажет, сколько файлов браузер реально положил в поле. Если файлы в поле есть, а сайт не реагирует, добавьте событие change через Evaluate.
Есть ли в chromedp действие, заполняющее форму из карты целиком?
Нет: в текущей библиотеке массовой установки значений формы одним вызовом нет — если в старых статьях встречается имя вроде SetSubmissionValues, в актуальном API его не ищите. Рабочие пути: цикл SetValue по полям или один Evaluate с выражением, которое раскладывает значения и возбуждает события, — на формах с десятками полей это заметно быстрее.
Термины урока
Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.
Изучайте дальше
Следующая ступень учебного пути
Testcontainers в Go: интеграционные тесты с Docker
Курс testcontainers-go: Postgres, Redis, Kafka и Mongo в тестах через Docker, wait-стратегии, сети, параллельность, CI и итоговый стенд. 25 уроков.
- Поднимать реальные зависимости в Docker из кода теста
- Использовать модули Postgres, Redis, MongoDB, Kafka и RabbitMQ
- Ждать готовность сервиса wait-стратегиями вместо sleep
- Собирать стенды из нескольких контейнеров и своего образа