Кластеризация

Для работы с Puppeteer в среде JavaScript необходим Node.js версии не ниже 14. Установка осуществляется через npm:

npm install puppeteer

Импортировать библиотеку можно стандартным образом:

const puppeteer = require(&

Создание браузера и страницы выполняется с помощью методов puppeteer.launch() и browser.newPage(). Пример инициализации:

(async () => {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await browser.close();
})();

Параметр headless контролирует видимость браузера: true запускает его в фоне, false — отображает окно для отладки.


Основы кластеризации

Кластеризация в контексте Puppeteer позволяет параллельно выполнять множество задач в отдельных экземплярах браузера или страниц. Это критично для ускорения тестирования и веб-скрейпинга больших объёмов данных, особенно если страницы нагружены JavaScript.

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


Использование библиотеки puppeteer-cluster

Для удобного управления кластерами применяется пакет puppeteer-cluster:

npm install puppeteer-cluster

Импорт и создание кластера:

const { Cluster } = require('puppeteer-cluster');

(async () => {
    const cluster = await Cluster.launch({
        concurrency: Cluster.CONCURRENCY_PAGE,
        maxConcurrency: 4,
        puppeteerOptions: { headless: true }
    });

    await cluster.task(async ({ page, data: url }) => {
        await page.goto(url);
        const title = await page.title();
        console.log(`Title of ${url} is ${title}`);
    });

    cluster.queue('https://example.com');
    cluster.queue('https://example.org');

    await cluster.idle();
    await cluster.close();
})();

Ключевые моменты:

  • concurrency определяет тип параллелизма. Доступны:

    • Cluster.CONCURRENCY_PAGE — отдельная страница на воркера.
    • Cluster.CONCURRENCY_CONTEXT — отдельный браузерный контекст, полезно для изоляции сессий.
    • Cluster.CONCURRENCY_BROWSER — отдельный браузер на воркера, максимум изоляции, но высокая нагрузка на память.
  • maxConcurrency — количество параллельных воркеров. Оптимальное значение зависит от ресурсов машины и сложности страниц.


Обработка ошибок и повторные попытки

Кластеры Puppeteer позволяют автоматически обрабатывать ошибки:

cluster.on('taskerror', (err, data, willRetry) => {
    if (willRetry) {
        console.warn(`Ошибка на ${data}. Повторная попытка...`);
    } else {
        console.error(`Ошибка на ${data}: ${err.message}`);
    }
});

Опция retryLimit задает количество повторов:

const cluster = await Cluster.launch({
    concurrency: Cluster.CONCURRENCY_PAGE,
    maxConcurrency: 4,
    puppeteerOptions: { headless: true },
    retryLimit: 3
});

Масштабирование задач

Кластеризация особенно полезна при скрейпинге сотен и тысяч страниц. Очередь задач строится динамически:

const urls = ['https://site1.com', 'https://site2.com', 'https://site3.com'];
urls.forEach(url => cluster.queue(url));

Каждый воркер выполняет задачу независимо. Можно передавать в cluster.queue не только строки, но и сложные объекты с данными для теста:

cluster.queue({ url: 'https://example.com', selector: '.item' });

Внутри task можно обращаться к этим данным:

await page.waitForSelector(data.selector);
const text = await page.$eval(data.selector, el => el.textContent);

Оптимизация ресурсов

При больших объёмах данных важно контролировать потребление памяти и CPU:

  • Headless режим снижает нагрузку на графическую подсистему.

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

  • Регулировка maxConcurrency предотвращает падение системы из-за перегрузки.

  • Закрытие ненужных страниц:

    await page.close();

Примеры комплексного использования

  1. Скрейпинг с сохранением результатов

const fs = require('fs');

const results = [];

await cluster.task(async ({ page, data: url }) => { await page.goto(url); const title = await page.title(); results.push({ url, title }); });

urls.forEach(url => cluster.queue(url));

await cluster.idle(); await cluster.close();

fs.writeFileSync('results.json', JSON.stringify(results, null, 2));

  1. Параллельное тестирование UI

Кластеризация позволяет одновременно проверять несколько сценариев:

const tests = [ { url: 'https://example.com/login', action:
'login' }, { url: 'https://example.com/signup', action: 'signup'
}];

await cluster.task(async ({ page, data }) => { await page.goto(data.url); if (data.action === 'login') { await page.type('#user', 'admin'); await page.type('#pass', '123'); await page.click('#submit'); } else if (data.action === 'signup') { await page.type('#email', 'test@example.com'); await page.click('#register'); } });

tests.forEach(test => cluster.queue(test));

Выводы по кластеризации

  • Ускоряет тестирование и скрейпинг, используя параллельные воркеры.
  • Позволяет изолировать сессии и страницы, что критично для сложных UI-тестов.
  • Облегчает обработку ошибок и повторов через встроенные механизмы puppeteer-cluster.
  • Гибко масштабируется под ресурсы машины с помощью параметров maxConcurrency и concurrency.

Кластеризация — базовый инструмент для любого серьезного проекта на Puppeteer, где важны скорость, надежность и масштабируемость параллельных задач.