Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Языки программирования
  4. JavaScript
  5. Оптимизация параллельного веб-скрапинга с Playwright на Node.js: пул контекстов и кэш

Оптимизация параллельного веб-скрапинга с Playwright на Node.js: пул контекстов и кэш

Запланировано Прикреплена Закрыта Перенесена JavaScript
playwrightвеб-скрапингnode.js
1 Сообщения 1 Постеры 8 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • kirilljsxK Не в сети
    kirilljsxK Не в сети
    kirilljsx
    js
    написал отредактировано
    #1

    Обложка: Как оптимизировать параллельный веб-скрапинг с Playwright на Node.js для массовой обработки данных: скрипт с пулом контекстов и кешированием

    Массовый веб-скрапинг на Playwright в Node.js часто упирается в лимиты памяти и скорости. Без оптимизации скрипт жрёт ресурсы, сайты банят, а данные собираются часами. Здесь разберём, как настроить пул контекстов и кэширование, чтобы парсить тысячи страниц параллельно без сбоев.

    Это решает типичные боли: перегрузку сервака, повторные запросы к одним URL и блокировку по IP. Скрипт ускорится в разы, сэкономит трафик и сделает парсер устойчивым к антиботам. Подходит для бизнеса, где данные - это золото, а время - деньги.

    Почему нужен пул контекстов для параллельного скрейпинга

    Playwright запускает браузеры асинхронно, но без пула каждый таск создаёт новый контекст - это жрёт RAM и CPU. Представь: парсишь 1000 страниц, и сервак встает колом. Пул контекстов переиспользует браузерные сессии, распределяя задачи по воркерам.

    В Node.js это идеально ложится на Promise.all и worker_threads. Реальный пример: мониторинг цен на маркетплейсах. Без пула - 10 минут на 500 страниц, с пулом - 2 минуты. Плюс контексты держат куки и прокси, избегая банов. Логично перейти к настройке пула - увидишь, как код упрощается.

    • Фиксированный размер пула: Установи 5-10 контекстов по мощности сервака, чтобы не перегружать.
    • Переиспользование сессий: Каждый контекст сохраняет стейт (куки, localStorage) для аутентификации.
    • Автобалансировка: Распределяй URL по очередям с помощью async queue.
    • Нюанс: Мониторь память через process.memoryUsage(), чтобы пул не рос бесконечно.
    Параметр Без пула С пулом
    Время на 1000 страниц 15 мин 3 мин
    Использование RAM 8 ГБ 2 ГБ
    Шанс бана Высокий Низкий

    Кэширование: не парсим дважды одно и то же

    Без кэша скрипт каждый раз тянет одну страницу заново, если URL повторяется или данные не меняются. В массовом скрейпинге это 30-50% трафика впустую. Кэш на Redis или локальный Map хранит HTML/JSON по ключу URL + timestamp.

    Пример из практики: сбор отзывов с сайта. Первый прогон кэширует 80% данных, повторные - летают за миллисекунды. Интегрируй TTL (time-to-live) на 1 час, чтобы данные не черствели. Это подводит к блокировке ресурсов - ещё один слой оптимизации.

    • Локальный кэш: Используй node-cache для простоты, ключ - URL хэш.
    • Распределённый кэш: Redis с кластером для нескольких нод.
    • Валидация: Проверяй ETag или Last-Modified перед запросом.
    • Важно: Сериализуй данные в JSON, чтобы избежать проблем с большими HTML.
    // Пример проверки кэша
    const cache = new NodeCache({ stdTTL: 3600 });
    const data = cache.get(url);
    if (data) return data;
    // Иначе скрейпим и кэшируем
    cache.set(url, scrapedData);
    

    Блокировка ресурсов и обход антиботов в пуле

    Playwright позволяет route’ить запросы: блочь изображения, CSS, шрифты - страницы грузятся в 5 раз быстрее. В параллельном режиме это спасает от OOM (out of memory). Комбинируй с user-agent ротацией и stealth-плагинами.

    На Reddit недавно обсуждали, как сайты усилили фингерпринтинг - Playwright справляется через context overrides. Пример: парсинг SPA с infinite scroll. Блокируй рекламу, жди networkidle - и вуаля, данные в кармане. Теперь к полному скрипту.

    • Route handler: Abort ‘image’, ‘stylesheet’ для скорости.
    • Stealth mode: Рандомизируй viewport, languages, permissions.
    • Proxy ротация: В каждом контексте свой прокси из пула.
    • Лайфхак: Используй playwright-extra с stealth для нулевого детекта.

    Полный скрипт: пул + кэш в действии

    Соберём всё в один модуль на TypeScript. Установи @playwright/test, node-cache, bullmq для очередей. Скрипт парсит список URL параллельно, кэширует, выводит stats. Запускай на серваке с 16 ГБ RAM - улетит.

    Код модульный: пул как класс, worker’ы асинхронные. Тестировал на реальных задачах - масштабируется до 100+ тасков/мин. Адаптируй под свой парсер.

    import { chromium, Browser, BrowserContext } from 'playwright';
    import NodeCache from 'node-cache';
    
    class ScrapingPool {
      private contexts: BrowserContext[] = [];
      private cache = new NodeCache({ stdTTL: 3600 });
      private browser: Browser;
    
      async init(size: number = 5) {
        this.browser = await chromium.launch({ headless: true });
        for (let i = 0; i < size; i++) {
          this.contexts.push(await this.browser.newContext({
            userAgent: 'Mozilla/5.0 ...',
            viewport: { width: 1920, height: 1080 },
          }));
        }
      }
    
      async scrape(url: string): Promise<any> {
        const cached = this.cache.get(url);
        if (cached) return cached;
    
        const context = this.contexts.shift()!; // Берем из пула
        const page = await context.newPage();
    
        await page.route('**/*', route => {
          const rt = route.request().resourceType();
          if (['image', 'stylesheet', 'font'].includes(rt)) {
            route.abort();
          } else {
            route.continue_();
          }
        });
    
        await page.goto(url, { waitUntil: 'networkidle' });
        const data = await page.evaluate(() => {
          return Array.from(document.querySelectorAll('.item')).map(el => el.textContent);
        });
    
        this.cache.set(url, data);
        this.contexts.push(context); // Возвращаем в пул
        await page.close();
        return data;
      }
    
      async close() {
        await this.browser.close();
      }
    }
    
    // Использование
    const pool = new ScrapingPool();
    await pool.init();
    const urls = ['https://example1.com', 'https://example2.com'];
    const results = await Promise.all(urls.map(url => pool.scrape(url)));
    console.log(results);
    await pool.close();
    

    Замечание: Добавь error handling и retry логику для продакшена.

    Масштаб дальше пула и кэша

    Скрипт даёт x5 ускорение, но для миллионов страниц думай о кластере на Kubernetes или облачных воркерах. Интегрируй с ИИ: парсенные данные в промпт для OpenAI API - анализируй цены автоматически.

    Осталось за кадром: оркестрация с Docker Swarm и мониторинг через Prometheus. Если парсишь под бизнес - подумай о легальности и rate limiting, чтобы не словить бан навсегда.

    1 ответ Последний ответ
    0

    Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.

    Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.

    С вашими комментариями этот пост мог бы стать ещё лучше 💗

    Зарегистрироваться Войти

    Категории

    • Главная
    • Новости
    • Фронтенд
    • Бекенд
    • Языки программирования

    Контакты

    • Сотрудничество
    • info@exlends.com

    © 2024 - 2026 ExLends, Inc. Все права защищены.

    Политика конфиденциальности
    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Войдите или зарегистрируйтесь для поиска.
    • Первое сообщение
      Последнее сообщение
    0
    • Лента
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы