Дебаты по поводу выбора между Playwright и Puppeteer — это большая дискуссия, поскольку они обе являются фантастическими библиотеками Node.js для автоматизации браузера. Хотя эти библиотеки делают практически одно и то же, между Puppeteer и Playwright есть несколько заметных различий.

Давайте проведем краткий экскурс в историю:

Puppeteer был создан командой разработчиков Chrome в 2017 году, чтобы компенсировать ненадежность Selenium для автоматизации браузеров. Playwright был позже запущен Microsoft и, как и Puppeteer, способен эффективно выполнять сложные тесты автоматизации в браузере. Но на этот раз они представили больше инструментов для тестирования. Так какой же из них лучше?

Давайте рассмотрим различия между Puppeteer и Playwright, чтобы понять, в чем уникальность обеих библиотек.

Playwright по сравнению с Puppeteer: в чем основные различия?

Puppeteer и Playwright — это headless‑браузеры, изначально предназначенные для сквозного автоматизированного тестирования веб‑приложений. Они использовались и для других целей, например, для веб‑скрейпинга. Несмотря на то, что у обоих инструментов автоматизации имеются схожие юзкейсы, существуют некоторые ключевые различия:

  • Playwright поддерживает Python, Golang, Java, JavaScript и C#, в то время как Puppeteer поддерживает только JavaScript, хотя существует неофициальный порт для Python.

  • Playwright поддерживает три браузера: Chromium, Firefox или WebKit. А Puppeteer, в свою очередь, поддерживает только Chromium.

Playwright

Playwright — это библиотека для сквозного веб‑тестирования и автоматизации. Хотя основная роль фреймворка заключается в тестировании веб‑приложений, его можно использовать для веб‑скрейпинга.

В чем преимущества Playwright?

  • Благодаря единому API библиотека позволяет вам использовать Chromium, Firefox или WebKit для тестирования. Кроме того, кроссплатформенный фреймворк быстро запускается в Windows, Linux и MacOS.

  • Playwright поддерживает Python, Golang, Java, JavaScript и C#.

  • Playwright работает быстрее, чем большинство фреймворков для тестирования, таких как Cypress.

Каковы недостатки Playwright?

  • В Playwright отсутствует поддержка Ruby и Java.

  • Вместо реальных устройств Playwright использует десктопные браузеры для эмуляции мобильных устройств.

Playwright параметры браузера

Параметры браузера и страничные методы управляют тестовой средой.

  • Headless: определяет, будет ли вам виден браузер во время тестирования. В качестве дефолтного значения установлено false. Вы можете изменить его на true, чтобы видеть браузер во время тестирования.

  • SlowMo: замедленное движение уменьшает скорость переключения между действиями на странице. Например, значение 500 означает задержку на 500 миллисекунд.

  • DevTools: Открывает Chrome Dev Tools при запуске целевой страницы. Обратите внимание, что эта опция работает только для Chromium.

await playwright.chromium.launch({ devtools: true })

Playwright методы объекта страницы 

Здесь представлены некоторые методы для управления страницей запуска.

Методы объекта

Значение

goto()

Посетите страницу в первый раз

reload()

Этот метод обновляет страницу

evaluate()

Этот метод предоставляет вам мини API для захвата элемента и манипулирования им с помощью JavaScript для DOM в среде Node.js.

В качестве альтернативы вы можете использовать $eval()$$eval(), $() и $$().

screenshot()

Чтобы сделать скриншот страницы.

setDefaultTimeout()

Он позволяет headless-браузеру ожидать действия в течение определенного времени, прежде чем выдать ошибку.

keyboard.press()

Этот метод позволяет указать клавишу, которую нужно нажать.

waitForSelector()

Он указывает странице отложить действие до тех пор, пока не будет загружен определенный селектор.

locator()

Класс локатора захватывает элементы, используя несколько комбинаций селекторов.

click()

Этот метод позволяет вам указать тег, селектор которого вы хотите кликнуть.

Веб-скрейпинг с помощью Playwright

В качестве небольшого учебного пособия, призванного помочь в обсуждении Playwright и Puppeteer, давайте воспользуемся Playwright чтобы соскрейпить названия товаров, цены и URL‑адреса изображений с Vue Storefront и сохраним результаты в CSV‑файл.

Начните с импорта модуля Playwright, а также модуля файловой системы (fs) для сохранения данных, которые вы соскрейпили в CSV‑файл.

import playwright from 'playwright' // web scraping 
import fs from 'fs' // saving data to CSV

Не забудьте указать тип модуля в файле package.json, иначе синтаксис import не будет работать.

Поскольку Playwright выполняется в асинхронной среде, а синтаксис async-await работает только в асинхронной функции, вы можете создать асинхронную функцию main и прописать в ней скрейпер.

const main = async () => { 
	// write some code 
} 
main()

Следующим шагом будет запуск браузера и создание новой страницы — давайте запустим Chromium в режиме headed.

const browser = await playwright.chromium.launch({ headless: false })

Вы открыли браузер, поздравляем, теперь мы уже на полпути к цели. Создайте объект страницы с помощью метода newPage() API браузера.

const page = await browser.newPage()

Чтобы получить подробную информацию о товаре из Vue Storefront, давайте посетим страницу категории "Кухня" (kitchen) и отсортируем элементы по "Самым новым" (Newest).

await page.goto('https://demo.vuestorefront.io/c/kitchen?sort=NEWEST')

В качестве альтернативы вы можете автоматизировать работу скрейпера, чтобы он определял расположение и кликал по элементам каждый раз, пока не попадет на целевую страницу.

Давайте создадим CSV-файл и напишем его заголовки, чтобы соскрейпить название, цену и URL-адреса изображений.

fs.writeFileSync('products.csv', 'title,price,imageUrl\n')

Вы можете найти элемент div, содержащий товары, с помощью селектора классов CSS и сохранить полученный массив элементов в переменной products (товары).

 const products = await page.$$('.products__grid > .sf-product-card.products__product-card')

Используя цикл for-of, извлеките заголовок, цену и URL изображения из каждого дочернего элемента (продукта), как показано ниже:

for (const product of products) { 
	let title, price, imageUrl 
	// extracting the target portions into title, price and image urls, respectively 
	title = await page.evaluate(e => e.querySelector('.sf-product-card__title').textContent.trim(), product) 
	price = await page.evaluate(e => e.querySelector('.sf-price__regular').textContent.trim(), product) 
	imageUrl = await page.evaluate(e => e.querySelector('.sf-image.sf-image-loaded').src, product) 
	// for every loop, append the extracted data into the CSV file 
	fs.appendFile('products.csv', `${title},${price},${imageUrl}\n`, e => { if (e) console.log(e) }) 
}

Закройте браузер и выполните файл скрипта.

await browser.close()

И вот! Получилась идеально соскрейпенная с помощью Playwright веб-страница.

На случай, если вы запутаетесь, вот как выглядит полный код:

// in index.js 
 
// Import the modules: playwright (web scraping) and fs (saving data to CSV) 
import playwright from 'playwright' 
import fs from 'fs' 
 
// create asynchronous main function 
const main = async () => { 
	// launch a visible chromium browser 
	const browser = await playwright.chromium.launch({ headless: false }) 
 
	// create a new page object 
	const page = await browser.newPage() 
	// visit the target page 
	await page.goto('https://demo.vuestorefront.io/c/kitchen?sort=NEWEST') 
	// create a CSV file, in readiness to save the data we are about to scrape 
	fs.writeFileSync('products.csv', 'title,price,imageUrl\n') 
 
	// download an array of divs containing the target data 
	const products = await page.$$('.products__grid > .sf-product-card.products__product-card') 
	// loop through the array, 
	for (const product of products) { 
		let title, price, imageUrl 
		// dissecting the target portions into title, price and image urls, respectively 
		title = await page.evaluate(e => e.querySelector('.sf-product-card__title').textContent.trim(), product) 
		price = await page.evaluate(e => e.querySelector('.sf-price__regular').textContent.trim(), product) 
		imageUrl = await page.evaluate(e => e.querySelector('.sf-image.sf-image-loaded').src, product) 
		// for every loop, append the dissected data into the already created CSV file 
		fs.appendFile('products.csv', `${title},${price},${imageUrl}\n`, e => { if (e) console.log(e) }) 
	} 
	// Close the (running headless) browser when the mission is accomplished 
	await browser.close() 
} 
 
// don't forget to run the main() function 
main()

Puppeteer

Puppeteer — это библиотека автоматизации для JavaScript (Node.js), и, в отличие от Playwright, Puppeteer загружает и использует Chromium по умолчанию. Она больше ориентирована на Chrome DevTools, что делает ее одной из лучших библиотек для веб‑скрейпинга.

В чем преимущества Puppeteer?

Puppeteer упрощает начало работы по автоматизации браузера. Она управляет Chrome с помощью нестандартного протокола DevTools.

Каковы недостатки Puppeteer?

  • Puppeteer поддерживает только JavaScript (Node.js).

  • Хотя ведется разработка поддержки Firefox, в настоящее время Puppeteer поддерживает только Chromium.

Опции браузера в Puppeteer

Большинство опций браузера из Playwright, такие как headless, slowMo и devtools, работают и в Puppeteer.

await puppeteer.launch({ headless: false, slowMo: 500, devtools: true })

Методы объекта страницы в Puppeteer

Большинство методов объекта страницы Playwright работают и в Puppeteer. Вот некоторые из них.

Методы объекта

Значение

goto()

Посетите страницу в первый раз

goForward()

Перейти вперед

goBack()

Вернуться на предыдущую страницу

reload()

Этот метод обновляет страницу

evaluate() 

Этот метод предоставляет вам мини API для захвата элемента и манипулирования им с помощью JavaScript для DOM в среде Node.js. В качестве альтернативы можно использовать $eval()$$eval(), $() и $$().

screenshot() 

Чтобы сделать скриншот страницы.

setDefaultTimeout() 
или 
setDefaultNavigationTimeout()

Позволяет headless-браузеру ожидать действия в течение заданного времени, прежде чем выдать ошибку.

keyboard.press()

Этот метод позволяет указать клавишу для нажатия.

waitForSelector()

Указывает странице отложить действие до тех пор, пока не будет загружен определенный селектор.

waitFor()  

Для задержки последующих действий.

locator()

Класс локатора захватывает элементы, используя несколько комбинаций селекторов.

click()

Этот метод позволяет вам указать тег, селектор которого вы хотите кликнуть.

select()

Для выбора опции в элементе select. 

Веб-скрейпинг с помощью Puppeteer

Чтобы соскрейпить веб‑страницу с помощью Puppeteer, импортируйте модуль Puppeteer для веб‑скрейпинга и модуль fs для сохранения соскрейпенных данных в CSV‑файл.

import puppeteer from 'puppeteer' // web scraping 
import fs from 'fs' // saving scraped data 

Создайте асинхронную функцию для запуска headless-браузера.

const main = async () => { 
	// write some code 
} 
main()

Теперь запустите headless-браузер и создайте новую страницу.

const browser = await puppeteer.launch({ headless: false }) 
const page = await browser.newPage()

Используя метод goto(), посетите целевую страницу, прежде чем начать скрейпинг данных.

await page.goto('https://demo.vuestorefront.io/c/kitchen?sort=NEWEST')

Затем создайте CSV-файл для хранения соскрейпенных данных.

fs.writeFileSync('products.csv', 'title,price,imageUrl\n')

Найдите и просмотрите данные с веб-страницы

const products = await page.$$('.products__grid > .sf-product-card.products__product-card')

Используя цикл for-of, извлеките название, цену и URL изображения товаров перед добавлением данных в CSV-файл.

for (const product of products) { 
	let title, price, imageUrl 
	// extracting the target portions into title, price and image urls, respectively 
	title = await page.evaluate( e => e.querySelector('.sf-product-card__title').textContent.trim(), product) 
	price = await page.evaluate( e => e.querySelector('.sf-price__regular').textContent.trim(), product) 
	imageUrl = await page.evaluate( e => e.querySelector('.sf-image.sf-image-loaded').src, product) 
	// for every loop, append the extracted data into the CSV file 
	fs.appendFile('products.csv', `${title},${price},${imageUrl}\n`, e => { if (e) console.log(e) }) 
}

Наконец, закройте браузер и запустите скрипт.

await browser.close()

Поздравляем, вы только что соскрейпили веб-страницу с помощью Puppeteer. ????.

Вот как выглядит полная версия кода:

// Import the modules: puppeteer (web scraping) and fs (saving data to CSV) 
import puppeteer from 'puppeteer' 
import fs from 'fs' 
 
// create asynchronous main function 
const main = async () => { 
	// launch a headed chromium browser 
	const browser = await puppeteer.launch({ headless: false }) 
 
	// create a new page object 
	const page = await browser.newPage() 
	// visit the target page 
	await page.goto('https://demo.vuestorefront.io/c/kitchen?sort=NEWEST') 
	// create a CSV file, in readiness to save the data we are about to scrape 
	fs.writeFileSync('products.csv', 'title,price,imageUrl\n') 
 
	// download an array of divs containing the target data 
	const products = await page.$$('.products__grid > .sf-product-card.products__product-card') 
	// loop through the array, 
	for (const product of products) { 
		let title, price, imageUrl 
		// dissecting the target portions into title, price and image urls, respectively 
		title = await page.evaluate( e => e.querySelector('.sf-product-card__title').textContent.trim(), product) 
		price = await page.evaluate( e => e.querySelector('.sf-price__regular').textContent.trim(), product) 
		imageUrl = await page.evaluate( e => e.querySelector('.sf-image.sf-image-loaded').src, product) 
		// for every loop, append the dissected data into the already created CSV file 
		fs.appendFile('products.csv', `${title},${price},${imageUrl}\n`, e => { if (e) console.log(e) }) 
	} 
	// Close the (running headless) browser when the mission is accomplished 
	await browser.close() 
} 
 
// don't forget to run the main() function 
main()

Playwright или Puppeteer: что быстрее?

Сравнение производительности Puppeteer и Playwright может оказаться сложной задачей, но попробуем выяснить, какая библиотека окажется на первом месте.

Давайте создадим третий файл сценария под названием performance.js и запустим в нем Playwright и Puppeteer, засекая время, которое требуется каждой функции для скрейпинга данных Vue Storefront.

// in performance.js 
 
const playwrightPerformance = async () => { 
	// START THE TIMER 
	console.time('Playwright') 
	// Playwright scraping code 
	// END THE TIMER 
	console.timeEnd('Playwright') 
} 
 
const puppeteerPerformance = async () => { 
	// START THE TIMER 
	console.time('Puppeteer') 
	// Puppeteer scraping code 
	// END THE TIMER 
	console.timeEnd('Puppeteer') 
} 
 
playwrightPerformance() 
puppeteerPerformance()

Мы вставим код скрейпинга Playwright и Puppeteer в соответствующие функции, настроим просмотр в режиме headless, а затем прогоним файл performance.js пять раз, чтобы определить среднее значение рантайма.

Вот средняя продолжительность работы для каждой библиотеки:

Playwright ➡️ (7,580 + 7,372 + 6,639 + 7,411 + 7,390) = (36,392 / 5) = 7,2784 с.

Puppeteer ➡️ (6.656 + 6.653 + 6.856 + 6.592 + 6.839) = (33.596 / 5) = 6.7192s

И по итогу Puppeteer побеждает в споре с Playwright по скорости работы!

Стоит отметить, что данные результаты основаны на нашем собственном тесте. Если вы хотите провести свой, воспользуйтесь мини-руководством, приведенным выше.

Лучше ли Playwright, чем Puppeteer?

Невозможно дать однозначный ответ на вопрос, что лучше: Puppeteer или Playwright, поскольку это зависит от множества факторов, таких как долгосрочная поддержка библиотек, поддержка кросс-браузерности и ваши конкретные потребности относительно автоматизации браузера.

Вот некоторые из наиболее значимых фич Playwright и Puppeteer:

Функциональность

 Playwright

Puppeteer

Поддерживаемые языки

Python, Java, JavaScript и C#

JavaScript

Поддерживаемые браузеры

Chromium, Firefox и WebKit

Chromium

Скорость  

быстрая

быстрее

Распространенная проблема, с которой сталкиваются при веб‑скрейпинге, заключается в том, что некоторые сайты могут детектировать ботов и блокируют ваш headless‑браузинг, особенно если вы часто кликаете на кнопки и отправляете множественный трафик за короткое время. Одним из решений является введение таймеров перед последующими действиями.

Например, вы можете запрограммировать Puppeteer на имитацию пользователя (человека), выжидая 0,1 с перед кликом на кнопку после ввода данных в форму для авторизации. Однако недостатком множественных таймеров является то, что они замедляют браузинг, и большинство веб‑сайтов даже могут их засечь (детектировать).

API ZenRows отлично решает эту проблему, он способен справиться со всеми анти‑ботами и обходом CAPTCHA вместо вас, и это лишь малая часть того, на что он способен. Воспользуйтесь бесплатной пробной версией, чтобы узнать, почему это святой Грааль для веб‑скрейпинга.

Перевод статьи подготовлен в преддверии старта специализации QA Automation Engineer. Хочу порекомендовать вам два бесплатных урока курса, на первом из которых поговорим о той документации, которую составляет тестировщик, а именно: дефекты, чек‑листы, тест‑кейсы. А на втором занятии обсудим различные виды тестирования. Научимся отличать черные коробки от белых, регрессионное тестирование от дымового. В результате вы научитесь структурировано подготавливать тест‑кейсы и составлять чек‑листы. Занятие будет интересно всем, кто хочет стать тестировщиком. Зарегистрироваться на каждый из уроков можно по ссылкам ниже.

Комментарии (2)


  1. iBljad
    00.00.0000 00:00

    Playwright поддерживает Python, Golang, Java, JavaScript и C#.

    В Playwright отсутствует поддержка Ruby и Java

    Понятно, что перевод, но всё же (правильный ответ: поддерживает)


  1. kozikoff
    00.00.0000 00:00

    У вас в недостатках написано, что playwright не поддерживает джаву. А в преимуществах, что поддерживает. Подозрительно…