Генерация отчетов в PDF

Puppeteer предоставляет удобные инструменты для создания автоматических тестов для веб-приложений. Одной из полезных возможностей является генерация отчетов в PDF, что позволяет легко фиксировать и сохранять результаты работы приложения в удобном формате. В этой главе рассмотрим, как с помощью Puppeteer можно генерировать PDF-документы, используя различные настройки и опции.

Для создания PDF с помощью Puppeteer используется метод page.pdf(). Этот метод позволяет захватить содержимое страницы и сохранить его в формате PDF. Функция имеет несколько настроек, которые позволяют настраивать внешний вид и поведение генерируемого файла.

const puppeteer = require(&

async function generatePDF() {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  // Открытие веб-страницы
  await page.goto('https://example.com');

  // Генерация PDF
  await page.pdf({
    path: 'report.pdf',  // Путь к файлу, куда будет сохранен PDF
    format: 'A4',        // Формат страницы
    printBackground: true, // Включить вывод фона
  });

  await browser.close();
}

generatePDF();

В примере выше создается PDF-документ с содержимым веб-страницы, расположенной по адресу https://example.com. Файл будет сохранен в текущей директории с именем report.pdf.

Опции для настройки PDF

Метод page.pdf() поддерживает несколько опций, которые позволяют настраивать итоговый документ:

  • path: Указывает путь и имя файла, в который будет сохранен PDF. Если параметр не задан, PDF будет выводиться в виде потока, который можно будет обработать в коде.

  • format: Устанавливает формат страницы. Возможные значения:

    • ‘A4’ — стандартный формат A4.
    • ‘Letter’ — формат Letter (для США).
    • Можно также использовать точные размеры в миллиметрах, например, { width: ‘210mm’, height: ‘297mm’ }.
  • landscape: Если задано значение true, страница будет ориентирована в альбомной (горизонтальной) ориентации.

  • printBackground: Определяет, нужно ли включать фон при генерации PDF. Значение true позволяет сохранять изображения фона и цвета.

  • margin: Устанавливает отступы вокруг страницы. Параметры могут быть заданы в виде объекта с ключами top, right, bottom, left, например, { top: ‘10mm’, bottom: ‘10mm’ }.

Пример с настройками:

await page.pdf({
  path: 'custom_report.pdf',
  format: 'A4',
  landscape: false,
  printBackground: true,
  margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
});

Генерация PDF для динамических страниц

Многие современные веб-приложения используют динамическую загрузку контента через JavaScript. Для корректной генерации PDF важно убедиться, что все необходимые элементы страницы загружены и отображаются. В Puppeteer можно использовать функцию waitForSelector() или waitForFunction() для ожидания загрузки динамического контента перед генерацией PDF.

await page.goto('https://example.com');
await page.waitForSelector('.dynamic-content'); // Ожидаем загрузку контента
await page.pdf({
  path: 'dynamic_content_report.pdf',
  format: 'A4',
});

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

Включение и настройка заголовков и подвалов

Для создания отчетов с заголовками и подвалами в PDF можно использовать параметр displayHeaderFooter. Он позволяет добавить в документ текстовые блоки вверху и внизу каждой страницы. Параметры для настройки:

  • displayHeaderFooter: Если задано значение true, будет добавлен заголовок и подвал.
  • headerTemplate: Шаблон для верхней части страницы (можно использовать HTML).
  • footerTemplate: Шаблон для нижней части страницы (также HTML).
  • fontSize: Размер шрифта для текста в заголовке и подвале.
  • height: Высота для заголовка и подвала.

Пример с заголовками и подвалами:

await page.pdf({
  path: 'report_with_header_footer.pdf',
  format: 'A4',
  displayHeaderFooter: true,
  headerTemplate: '<div style="font-size: 10px; text-align: center;">My Report</div>',
  footerTemplate: '<div style="font-size: 10px; text-align: center;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>',
  fontSize: 10,
});

Генерация PDF для сложных элементов

При работе с веб-страницами, содержащими сложные элементы, такие как таблицы с большими объемами данных, можно столкнуться с проблемой разбиения контента на страницы. Для корректной генерации можно использовать параметр pageRanges, который позволяет указать диапазоны страниц для вывода.

await page.pdf({
  path: 'large_report.pdf',
  format: 'A4',
  pageRanges: '1-2', // Генерирует только первые две страницы
});

Если необходимо гарантировать, что таблицы и другие элементы не будут разрывать страницу, следует использовать CSS-свойства, такие как page-break-before, page-break-after и page-break-inside для контроля над разбиением контента на страницы.

Сохранение PDF без фона

Для некоторых случаев может понадобиться создание PDF-документа без фона, чтобы сэкономить ресурсы и уменьшить размер файла. Это можно сделать, установив параметр printBackground в false.

await page.pdf({
  path: 'report_no_background.pdf',
  printBackground: false,
});

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

Генерация PDF с вложенными изображениями

Puppeteer также поддерживает генерацию PDF-документов с изображениями, которые могут быть встроены в содержимое страницы. Важно убедиться, что изображения корректно загружены перед созданием PDF. Если изображения загружаются асинхронно, следует ожидать их загрузки с помощью методов Puppeteer, таких как waitForSelector() или waitForFunction().

Пример с изображением:

await page.goto('https://example.com');
await page.waitForSelector('img');  // Ожидаем, что все изображения загружены
await page.pdf({
  path: 'report_with_images.pdf',
  format: 'A4',
  printBackground: true,
});

Оптимизация производительности при генерации PDF

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

  1. Отключать ресурсы. Если нет необходимости в загрузке внешних ресурсов, таких как изображения или шрифты, можно отключить их с помощью метода page.setRequestInterception(true) и перехвата запросов для блокировки лишних элементов.

    await page.setRequestInterception(true);
    page.on('request', (request) => {
      if (['image', 'stylesheet', 'font'].includes(request.resourceType())) {
        request.abort();
      } else {
        request.continue();
      }
    });
  2. Использовать headless-режим. Для генерации PDF всегда рекомендуется использовать headless-режим (без графического интерфейса), так как это значительно ускоряет процесс.

  3. Ожидание загрузки ресурсов. Убедитесь, что все ресурсы, такие как шрифты, изображения и стили, полностью загружены перед генерацией PDF, чтобы избежать проблем с отсутствующими элементами.

Работа с локальными ресурсами

Puppeteer позволяет генерировать PDF из локальных файлов HTML. Для этого можно использовать метод page.setContent() для загрузки HTML-контента, а затем вызвать page.pdf() для создания документа.

const htmlContent = '<html><body><h1>Test PDF</h1></body></html>';
await page.setContent(htmlContent);
await page.pdf({ path: 'local_report.pdf' });

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

Заключение

Генерация PDF-документов с использованием Puppeteer предоставляет гибкость и мощные возможности для автоматизации создания отчетов. Важно понимать, как настраивать параметры документа и учитывать особенности работы с динамическим контентом. Используя описанные методы и опции, можно создавать PDF-документы с нужным оформлением и содержанием, что удобно для создания отчетности, анализа данных и других приложений, где требуется сохранение результатов в формате PDF.