Контент, отображаемый с помощью JavaScript

8 мар. 2025 г.

Современные веб-приложения редко предоставляют полный HTML - вместо этого контент динамически загружается и отображается с помощью JavaScript. Это создает уникальные проблемы для веб-скрапинга, которые мы решим в этих двух главах.

Глава 4: Динамическая новостная лента

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

  • Автоматизация браузера с Playwright
  • Ожидание загрузки динамического контента
  • Обработка элементов DOM, отрисованных с помощью JavaScript

Структура страницы выглядит примерно так:

<div class="news-feed">
  <article class="news-item">
    <h2>Заголовок новости</h2>
    <p>Содержание статьи...</p>
    <div class="meta">
      <span>Автор: Имя Автора</span>
      <time datetime="2024-03-08T12:00:00Z">Март 8, 2024</time>
    </div>
  </article>
  <!-- Больше статей загружается динамически -->
</div>

Ключевые отличия от скрапинга статического HTML:

// Вместо cheerio.load() мы используем Playwright
const browser = await chromium.launch();
const page = await browser.newPage();

// Ожидание отрисовки контента
await page.waitForSelector('.news-item');

// Извлечение данных из живого DOM с помощью page.$$eval()
// Это запускает функцию обратного вызова в контексте браузера
// чтобы оценить все элементы, соответствующие селектору, сразу
const items = await page.$$eval('.news-item', elements => {
  // Работает как Array.map() для соответствующих элементов
  // Возвращает сериализуемые JavaScript-объекты
  // Идеально подходит для извлечения данных из нескольких элементов
});

Глава 5: Галерея с бесконечной прокруткой

Опираясь на наши знания о динамическом контенте, мы решаем еще более сложный сценарий - фотогалерею с бесконечной прокруткой. Это знакомит нас с:

  • Обработкой лениво загружаемого контента
  • Обнаружением и вызовом событий прокрутки
  • Управлением асинхронными состояниями загрузки
  • Извлечением данных из сложных шаблонов интерфейса

Сложность здесь заключается в том, что контент загружается постепенно по мере прокрутки пользователем:

<div class="photo-gallery">
  <div class="photo-card">
    <img src="..." alt="Название фото" />
    <h2>Название фото</h2>
    <p>Автор: Имя Фотографа</p>
    <div class="flex">
      <span>❤️ 42</span>
    </div>
  </div>
  <!-- Больше фотографий загружается при прокрутке -->
</div>

Ключевые концепции для обработки бесконечной прокрутки:

// Прокрутка вниз до тех пор, пока не загрузится новый контент
let previousHeight;
while (true) {
  previousHeight = await page.evaluate('document.body.scrollHeight');
  await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
  await page.waitForTimeout(1500); // Ожидание загрузки контента

  const newHeight = await page.evaluate('document.body.scrollHeight');
  if (newHeight === previousHeight) {
    break; // Больше нет контента для загрузки
  }
}

Важные моменты

При работе с контентом, отрисованным с помощью JavaScript:

  1. Производительность: Скрапинг динамического контента медленнее, чем статического HTML
  2. Управление ресурсами: Автоматизация браузера использует больше системных ресурсов
  3. Стабильность: Необходимо обрабатывать состояния загрузки и сетевые условия
  4. Ограничение скорости: Рассмотрите возможность добавления задержек между действиями

Лучшие практики

  1. Используйте подходящие стратегии ожидания:
// Ожидание конкретных элементов
await page.waitForSelector('.selector');

// Ожидание завершения сетевой активности
await page.waitForLoadState('networkidle');

// Пользовательские условия ожидания
await page.waitForFunction(() => {
  // Пользовательское JavaScript-условие
});
  1. Реализуйте надежную обработку ошибок:
try {
  await page.goto(url);
  // ... логика скрапинга
} catch (error) {
  console.error('Скрапинг не удался:', error);
} finally {
  await browser.close(); // Всегда освобождайте ресурсы
}
  1. Рассмотрите возможность реализации механизмов повторных попыток для повышения надежности
  2. Отслеживайте использование памяти при работе с большими наборами данных
  3. Проверяйте извлеченные данные на согласованность

Тестирование Вашего решения

Тестовая среда предоставляет мок-API, которые имитируют реальные условия:

  • Переменное время загрузки
  • Сетевая задержка
  • Механизмы пагинации
  • Состояния ошибок

Попробуйте эти вариации:

  1. Измените время прокрутки
  2. Обработайте разные размеры экрана
  3. Протестируйте с медленными сетевыми условиями
  4. Проверьте целостность данных

Готовы к обработке динамического контента? Код задачи и тестовые среды находятся в репозитории.

Проверьте решенные примеры в _solved/chapter4/ и _solved/chapter5/ для реализаций для справки. Помните - современный веб-скрапинг заключается в понимании как структуры HTML, так и поведения приложения.

Удачного скрапинга!