Автор статьи: «Ночная команда NightTeam» — Чжан Ецин
Ретушь, корректура: "NightTeam" - Loco
предисловие
Автоматизированное тестирование является очень важной и удобной вещью для разработки программного обеспечения, но в дополнение к тестированию инструменты автоматизированного тестирования также могут использоваться для имитации действий человека, поэтому некоторые инструменты автоматизированного тестирования E2E (такие как: Selenium, Puppeteer, Appium) из-за его мощная функция моделирования, она часто используется инженерами-краулерами для сканирования данных.
В Интернете есть много учебных пособий по сканированию, использующих инструменты автоматического тестирования в качестве краулеров, но они ограничиваются только тем, как получить данные, и мы знаем, чтоЭти решения на основе браузера имеют большую нагрузку на производительность и неэффективны, поэтому они не лучший выбор для поисковых роботов..
В этой статье будет представлено еще одно применение инструментов автоматизированного тестирования, а именно использованиеАвтоматизировать некоторые ручные операции. Инструмент, который мы используем, — это Puppeteer, среда тестирования, разработанная Google с открытым исходным кодом, которая использует Chromium (браузер с открытым исходным кодом, разработанный Google) для автоматизации. Мы расскажем вам, как использовать Puppeteer для автоматической публикации статей на Nuggets.
Принципы инструментов автоматизированного тестирования
Принцип инструментов автоматизированного тестирования заключается в управлении просматриваемыми веб-страницами путем программного управления браузером и имитации взаимодействия с ним (например, щелчки, ввод текста, навигация и т. д.). Инструменты автоматического тестирования обычно также могут получить DOM или HTML веб-страницы, поэтому они также могут легко получить данные веб-страницы.
Кроме того, для некоторых динамических веб-сайтов данные, отображаемые с помощью JS, обычно нелегко получить, но инструменты автоматического тестирования могут легко это сделать, поскольку они запускаются путем ввода HTML в браузере.
Введение в Кукольника
Вот выдержка из определения на домашней странице Github Puppeteer (на английском языке).
Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.
Примерный перевод: PuPpeteer — это библиотека node.js, предоставляющая расширенный API для управления Chrome или Chromium; режим PuPpeteer по умолчанию — без головы, но его можно настроить на режим без головы.
Примечание Loco: Headless относится к графическому интерфейсу, который не отображает браузер, и предназначен для повышения производительности, поскольку рендеринг изображений является ресурсоемкой задачей.
Вот что умеет Кукловод:
- Создание скриншотов и PDF-файлов страниц;
- Берите одностраничные приложения и создавайте предварительно обработанный контент (например, SSR, рендеринг на стороне сервера);
- Автоматизируйте отправку форм, тестирование пользовательского интерфейса, ввод с клавиатуры и многое другое;
- Создать современную автоматизированную тестовую среду;
- Захватите временную шкалу веб-сайта, чтобы помочь диагностировать проблемы с производительностью;
- Тестовый плагин Chrome;
- ...
Кукольная инсталляция
Установить Puppeteer несложно, просто убедитесь, что в вашей среде установлен Node.js и вы можете запускать NPM.
Так как в официальном руководстве по установке не учитывается, что Chromium был установлен, здесь мы используем стороннюю библиотеку.puppeteer-chromium-resolver
, который настраивает Puppeteer и управляет загрузками Chromium.
Выполните следующую команду, чтобы установить Puppeteer:
npm install puppeteer-chromium-resolver --save
puppeteer-chromium-resolver
Для подробного использования, пожалуйста, обратитесь к официальному сайту:уууу, эта лошадь plus.com/package/poof….
Общие команды кукловода
Официальная документация API для Puppeteer:pptr.dev/, в документе есть подробные открытые интерфейсы Puppeteer, можете на них сослаться, здесь мы лишь перечислим некоторые часто используемые команды интерфейса.
Создать/закрыть браузер
// 引入puppeteer-chromium-resolver
const PCR = require('puppeteer-chromium-resolver')
// 生成PCR实例
const pcr = await PCR({
revision: '',
detectionPath: '',
folderName: '.chromium-browser-snapshots',
hosts: ['https://storage.googleapis.com', 'https://npm.taobao.org/mirrors'],
retry: 3,
silent: false
})
// 生成浏览器
const browser = await pcr.puppeteer.launch({...})
// 关闭浏览器
await browser.close()
создать страницу
const page = await browser.newPage()
навигация
await page.goto('https://baidu.com')
ждать
await page.waitFor(3000)
await page.goto('https://baidu.com')
получить элемент страницы
const el = await page.$(selector)
щелкните элемент
await el.click()
Вход
await el.type(text)
Выполнить код консоли (выделено)
const res = await page.evaluate((arg1, arg2, arg3) => {
// anything frontend
return 'frontend awesome'
}, arg1, arg2, arg3)
Это, пожалуй, самый мощный API в Puppeteer. Любой разработчик, знакомый с интерфейсными технологиями, должен знать о консоли в инструментах разработчика Chrome, где можно запустить любой код JS, включая события кликов, получение элементов, добавление, удаление и изменение элементов и т. д. Наш автоматический издатель будет активно использовать этот API.
можно увидетьevaluate
Метод может принимать некоторые параметры и действовать как параметры в функции обратного вызова во внешнем коде. Это позволяет нам вводить любые данные из бэкэнда во внешний DOM, например, заголовки статей, их содержание и т. д.
Кроме того, возвращаемое значение в функции обратного вызова может использоваться какevaluate
Возвращаемое значение , присвоенноеres
, который часто используется для очистки данных.
Обратите внимание, что приведенный выше код используетсяawait
Это ключевое слово, которое на самом деле есть в ES7async/await
Новый синтаксис, ES6Promise
синтаксический сахар, облегчающий чтение и понимание асинхронного кода. если правильноasync/await
Для студентов, которые не понимают, вы можете обратиться к этой статье:nuggets.capable/post/684490….
Кукловод в действии: автоматически публикуйте статьи на Nuggets
Как говорится: говорить дешево, покажи код.
Ниже мы воспользуемся примером автоматической публикации статей, чтобы продемонстрировать возможности Puppeteer. В качестве примера в этой статье используется платформа Nuggets.
Почему выбирают Наггетс? Это связано с тем, что вход в систему Nuggets не похож на некоторые другие веб-сайты (такие как CSDN), которые требуют кода подтверждения (что увеличивает сложность), и для входа в систему требуется только имя учетной записи и пароль.
Чтобы облегчить понимание новичка, мы начнем с базовой структуры краулера. (Ограничено пространством, мы пропустим инициализацию браузера и страницы и сосредоточимся только на объяснении)
Базовая структура
Чтобы сканер выглядел менее запутанным, мы выделили различные этапы публикации статей и сформировали базовый класс (поскольку у нас может быть более одной платформы для захвата, если мы используем объектно-ориентированное мышление для написания кода, только для других платформ). необходимо наследовать от базового класса.)
Общая структура этого базового класса рептилий выглядит следующим образом:
Нам не нужно разбираться во всех методах, нам просто нужно знать, что запись, которую мы начинаем,run
Этот метод хорош.
Все методы добавленыasync
, указывая, что этот метод вернетPromise
, если его нужно вызывать синхронно, его нужно добавитьawait
это ключевое слово.
run
Содержание метода следующее:
async run() {
// 初始化
await this.init()
if (this.task.authType === constants.authType.LOGIN) {
// 登陆
await this.login()
} else {
// 使用Cookie
await this.setCookies()
}
// 导航至编辑器
await this.goToEditor()
// 输入编辑器内容
await this.inputEditor()
// 发布文章
await this.publish()
// 关闭浏览器
await this.browser.close()
}
Видно, что краулер сначала инициализирует и выполнит некоторые базовые настройки, затем по категории проверки задачи (authType
) решить, следует ли использовать логин или cookie для прохождения аутентификации на веб-сайте (в этой статье рассматривается только случай аутентификации при входе в систему); следующий шаг — перейти к редактору, а затем ввести содержимое редактора; затем опубликовать статью; наконец, закройте браузер и опубликуйте задачу Готово.
Авторизоваться
async login() {
logger.info(`logging in... navigating to ${this.urls.login}`)
await this.page.goto(this.urls.login)
let errNum = 0
while (errNum < 10) {
try {
await this.page.waitFor(1000)
const elUsername = await this.page.$(this.loginSel.username)
const elPassword = await this.page.$(this.loginSel.password)
const elSubmit = await this.page.$(this.loginSel.submit)
await elUsername.type(this.platform.username)
await elPassword.type(this.platform.password)
await elSubmit.click()
await this.page.waitFor(3000)
break
} catch (e) {
errNum++
}
}
// 查看是否登陆成功
this.status.loggedIn = errNum !== 10
if (this.status.loggedIn) {
logger.info('Logged in')
}
}
Адрес входа Nuggets:juejin.im/login, мы сначала просмотрим…
Здесь зацикливаемся 10 раз, пытаемся ввести логин и пароль, если все 10 раз не получается, ставим статус входа вfalse
; в противном случае установитьtrue
.
Далее мы использовалиpage.$(selector)
иel.type(text)
Эти два API используются для получения элементов и ввода содержимого соответственно. И последнееelSubmit.click()
это действие по отправке формы.
редактировать статью
Здесь мы пропускаем шаг перехода к редактору статьи, потому что это очень просто, просто вызовитеpage.goto(url)
Вот и все, адрес исходного кода будет опубликован позже для вашей справки.
Код для входа в редактор выглядит следующим образом:
async inputEditor() {
logger.info(`input editor title and content`)
// 输入标题
await this.page.evaluate(this.inputTitle, this.article, this.editorSel, this.task)
await this.page.waitFor(3000)
// 输入内容
await this.page.evaluate(this.inputContent, this.article, this.editorSel)
await this.page.waitFor(3000)
// 输入脚注
await this.page.evaluate(this.inputFooter, this.article, this.editorSel)
await this.page.waitFor(3000)
await this.page.waitFor(10000)
// 后续处理
await this.afterInputEditor()
}
Сначала введите название, позвонитеpage.evaluate
Этот интерфейс выполняет функцию, передаваяthis.inputTitle
Введите функцию обратного вызова заголовка и других параметров, затем по тому же принципу вызовите функцию обратного вызова входного содержимого, затем введите сноску и, наконец, вызовите последующую функцию обработки.
Ниже мы подробно рассмотримthis.inputTitle
Эта функция:
async inputTitle(article, editorSel, task) {
const el = document.querySelector(editorSel.title)
el.focus()
el.select()
document.execCommand('delete', false)
document.execCommand('insertText', false, task.title || article.title)
}
Сначала мы передаем публичный интерфейс фронтендаdocument.querySelector(selector)
Получить элемент заголовка. Чтобы заголовок не имел заполнителя, мы используемel.focus()
(сосредотачивается),el.select()
(выбрать все),document.execCommand('delete', false)
(удалить), чтобы удалить существующий заполнитель. Затем мы проходимdocument.execCommand('insertText', false, text)
для ввода содержимого заголовка.
Далее идет входной контент, код выглядит следующим образом (его принцип аналогичен входному заголовку):
async inputContent(article, editorSel) {
const el = document.querySelector(editorSel.content)
el.focus()
el.select()
document.execCommand('delete', false)
document.execCommand('insertText', false, article.content)
}
Можно спросить, а почему бы и нетel.type(text)
чтобы войти в контент, но это требует больших усилийdocument.execCommand
добиться ввода?
Причина, по которой мы не используем первый здесь, заключается в том, что он полностью имитирует набор текста на клавиатуре, что разрушит существующий формат контента. И если вы используете последний, вы можете ввести контент за один раз.
мы в базовом классеBaseSpider
В классе зарезервирован метод для завершения выбора классификации, метки и т. д. в унаследованном классе.JuejinSpider
вот так:
async afterInputEditor() {
// 点击发布文章
const elPubBtn = await this.page.$('.publish-popup')
await elPubBtn.click()
await this.page.waitFor(5000)
// 选择类别
await this.page.evaluate((task) => {
document.querySelectorAll('.category-list > .item').forEach(el => {
if (el.textContent === task.category) {
el.click()
}
})
}, this.task)
await this.page.waitFor(5000)
// 选择标签
const elTagInput = await this.page.$('.tag-input > input')
await elTagInput.type(this.task.tag)
await this.page.waitFor(5000)
await this.page.evaluate(() => {
document.querySelector('.suggested-tag-list > .tag:nth-child(1)').click()
})
await this.page.waitFor(5000)
}
выпуск
Операция публикации относительно проста, просто нажмите кнопку публикации. код показывает, как показано ниже:
async publish() {
logger.info(`publishing article`)
// 发布文章
const elPub = await this.page.$(this.editorSel.publish)
await elPub.click()
await this.page.waitFor(10000)
// 后续处理
await this.afterPublish()
}
this.afterPublish
Он используется для проверки статуса сообщения и получения URL-адреса сообщения, который не будет подробно описан здесь из-за нехватки места.
исходный код
Конечно, из-за длины этой статьи представлены не все функции автоматической публикации.Если вы хотите узнать больше, вы можете отправить сообщение [Nuggets Auto Post] в нашу общедоступную учетную запись WeChat [NightTeam], чтобы получить адрес исходного кода. .
Суммировать
В этой статье описывается, как использовать Puppeteer для управления браузером Chromium для публикации статей о Nuggets.
Многие люди используют Puppeteer для парсинга данных, но мы считаем, что это неэффективно и дорого, и не подходит для крупномасштабного парсинга.
Напротив, Puppeteer больше подходит для выполнения некоторой автоматизированной работы, такой как использование браузера для публикации статей, публикации сообщений, отправки форм и т. д.
Инструменты автоматизации Puppeteer очень похожи на RPA (Robotic Process Automation) в том смысле, что они автоматизируют некоторые утомительные и повторяющиеся задачи, но последний не ограничивается браузерами, его область действия основана на всей операционной системе и является более мощным, но накладные расходы также больше.
Как относительно легкий инструмент автоматизации, Puppeteer очень подходит для выполнения некоторых операций автоматизации веб-страниц. Фактический контент Puppeteer, представленный в этой статье, также является проектом мультидистрибутивной платформы с открытым исходным кодом.ArtiPubЧасть этого, заинтересованные студенты могут попробовать это.
Ночная команда была создана в 2019 году, и в нее входят Цуй Цинцай, Чжоу Цзыци, Чен Сянгань, Тан Ифэй, Фэн Вэй, Цай Цзинь, Дай Хуанцзинь, Чжан Ецин и Вэй Шидун.
Используемые языки программирования включают, помимо прочего, Python, Rust, C++, Go, а области охватывают поисковый робот, глубокое обучение, разработку услуг, хранилище объектов и т. д. Команда не добрая и не злая, они делают только то, что считают правильным, пожалуйста, будьте осторожны.
Эта статья опубликована на многопостовой платформеArtiPubавтоматическая публикация