Параллельный скрейпинг с Puppeteer
Скрейпинг — это процесс извлечения данных с веб-страниц с использованием автоматических инструментов. Puppeteer — это библиотека для Node.js, которая предоставляет API для управления браузером Chromium или Chrome через DevTools протокол. В этой главе рассмотрим, как использовать Puppeteer для выполнения параллельного скрейпинга, что позволяет ускорить процесс извлечения данных с нескольких страниц одновременно.
Обычные методы скрейпинга, выполняющие запросы поочередно, могут занять значительное время при обработке множества страниц, что увеличивает общую задержку. Параллельный скрейпинг позволяет запускать несколько процессов одновременно, распределяя нагрузку между ними, что в свою очередь значительно ускоряет процесс извлечения данных.
Основные преимущества параллельного скрейпинга:
Puppeteer позволяет управлять несколькими страницами или браузерными сессиями одновременно. Это можно сделать с помощью асинхронных функций и параллельных задач.
Для реализации параллельного скрейпинга в Puppeteer можно использовать несколько подходов, среди которых:
В большинстве случаев предпочтительнее использовать первый вариант, так как он экономит ресурсы, не открывая несколько экземпляров браузера, что может быть довольно ресурсоемким.
Для этого можно создать несколько вкладок в одном экземпляре браузера и выполнять параллельные задачи для каждой страницы.
const puppeteer = require(&
async function scrapePage(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
const data = await page.evaluate(() => {
return document.title; // Пример: получение заголовка страницы
});
await browser.close();
return data;
}
async function scrapeParallel(urls) {
const browser = await puppeteer.launch();
const promises = urls.map(async (url) => {
const page = await browser.newPage();
await page.goto(url);
const data = await page.evaluate(() => {
return document.title; // Пример: получение заголовка страницы
});
await page.close();
return data;
});
const results = await Promise.all(promises);
await browser.close();
return results;
}
const urls = ['https://example.com', 'https://example2.com', 'https://example3.com'];
scrapeParallel(urls).then((results) => {
console.log(results); // Вывод заголовков всех страниц
});
В этом примере создаются параллельные задачи для каждой страницы,
которые выполняются одновременно с использованием одного экземпляра
браузера. Каждый скрейпинг происходит в отдельной вкладке, и результаты
собираются с помощью Promise.all.
Если нужно запускать несколько браузеров (например, для более сильной изоляции задач или при большом количестве одновременных запросов), можно использовать несколько экземпляров Puppeteer.
const puppeteer = require('puppeteer');
async function scrapeParallelWithMultipleBrowsers(urls) {
const browserPromises = urls.map(async (url) => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
const data = await page.evaluate(() => {
return document.title;
});
await browser.close();
return data;
});
const results = await Promise.all(browserPromises);
return results;
}
const urls = ['https://example.com', 'https://example2.com', 'https://example3.com'];
scrapeParallelWithMultipleBrowsers(urls).then((results) => {
console.log(results);
});
Каждый браузер запускается в отдельном процессе, что позволяет добиться большей изоляции и параллельности, но это потребует больше системных ресурсов.
Хотя параллельный скрейпинг значительно ускоряет процесс сбора данных, следует учитывать некоторые моменты, связанные с производительностью:
Для более точного контроля над количеством одновременно выполняемых
задач можно использовать специальные библиотеки для управления
параллельными задачами, такие как Promise.allSettled,
async/await с лимитированием параллельных запросов или
библиотеки, такие как p-limit или bluebird.
Пример с использованием p-limit для ограничения
параллельных запросов:
const puppeteer = require('puppeteer');
const pLimit = require('p-limit');
const limit = pLimit(5); // Ограничение до 5 параллельных задач
async function scrapeParallelWithLimit(urls) {
const browser = await puppeteer.launch();
const promises = urls.map((url) =>
limit(async () => {
const page = await browser.newPage();
await page.goto(url);
const data = await page.evaluate(() => {
return document.title;
});
await page.close();
return data;
})
);
const results = await Promise.all(promises);
await browser.close();
return results;
}
const urls = ['https://example.com', 'https://example2.com', 'https://example3.com'];
scrapeParallelWithLimit(urls).then((results) => {
console.log(results);
});
Этот пример ограничивает количество параллельных запросов до 5 одновременно выполняющихся задач, что позволяет избежать чрезмерной нагрузки на систему.
При масштабировании скрейпинга, особенно при большом количестве параллельных запросов, существует вероятность, что сайт может применить защиту от ботов, такую как капча. Для обхода этого можно использовать различные подходы:
Параллельный скрейпинг в Puppeteer позволяет значительно повысить скорость извлечения данных с множества страниц. При правильной настройке можно эффективно использовать системные ресурсы, ускорить процесс и минимизировать задержки. Однако важно помнить о возможных ограничениях, связанных с производительностью и политиками защиты сайтов от ботов.