pdfkit – генерация PDF из HTML

онлайн тренажер по питону
Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое PDFKit для Python

PDFKit — это мощная Python-библиотека, представляющая собой обёртку над утилитой wkhtmltopdf, которая использует движок WebKit для преобразования HTML-документов в PDF-файлы. Эта библиотека позволяет разработчикам создавать профессиональные PDF-документы с сохранением сложной вёрстки, современных CSS-стилей, встроенных шрифтов, SVG-графики и даже JavaScript.

Основное преимущество PDFKit заключается в том, что он позволяет использовать знакомые веб-технологии (HTML, CSS) для создания документов, которые затем можно конвертировать в PDF с высоким качеством рендеринга. Это делает его идеальным инструментом для генерации отчётов, счетов-фактур, билетов, сертификатов и других документов с динамическим содержимым.

Возможности библиотеки PDFKit

Поддерживаемые технологии

  • Современный HTML5 и CSS3
  • Bootstrap, Tailwind CSS и другие CSS-фреймворки
  • SVG-графика и веб-шрифты
  • Таблицы с сложным форматированием
  • Flexbox и Grid-вёрстка
  • Медиа-запросы CSS
  • Базовая поддержка JavaScript

Источники данных для конвертации

PDFKit поддерживает конвертацию из трёх основных источников:

  • URL-адреса веб-страниц
  • Локальные HTML-файлы
  • HTML-строки в памяти приложения

Установка и настройка

Установка Python-библиотеки

pip install pdfkit

Установка wkhtmltopdf

Ubuntu/Debian:

sudo apt update
sudo apt install wkhtmltopdf

macOS (через Homebrew):

brew install --cask wkhtmltopdf

Windows: Скачайте установочный файл с официального сайта https://wkhtmltopdf.org/downloads.html. Доступны версии для Windows Vista и выше, как 32-битные, так и 64-битные варианты.

CentOS/RHEL/Amazon Linux:

# Для CentOS 7
sudo yum install wkhtmltopdf

# Для более новых версий
sudo dnf install wkhtmltopdf

Проверка установки

После установки убедитесь, что wkhtmltopdf доступен в системе:

wkhtmltopdf --version

Если команда не найдена, потребуется настроить путь к исполняемому файлу в коде Python.

Основные методы и функции

Создание PDF из различных источников

import pdfkit

# Из URL
pdfkit.from_url("https://example.com", "output.pdf")

# Из HTML-файла
pdfkit.from_file("template.html", "output.pdf")

# Из HTML-строки
html_content = "<h1>Заголовок</h1><p>Содержимое документа</p>"
pdfkit.from_string(html_content, "output.pdf")

Конфигурация пути к wkhtmltopdf

Если wkhtmltopdf не находится в системной переменной PATH, можно указать путь вручную:

config = pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf')
pdfkit.from_string(html_content, "output.pdf", configuration=config)

Генерация PDF в памяти

Для использования в веб-приложениях и API часто требуется получить PDF в виде байтов:

# Возвращает PDF как bytes
pdf_bytes = pdfkit.from_string(html_content, False)

# Можно отправить через HTTP-ответ
from flask import Response
return Response(pdf_bytes, mimetype='application/pdf')

Настройка параметров генерации

Основные опции форматирования

options = {
    'page-size': 'A4',
    'margin-top': '0.75in',
    'margin-right': '0.75in',
    'margin-bottom': '0.75in',
    'margin-left': '0.75in',
    'encoding': "UTF-8",
    'no-outline': None,
    'enable-local-file-access': None
}

pdfkit.from_string(html_content, "output.pdf", options=options)

Расширенные параметры

advanced_options = {
    'dpi': 300,  # Высокое качество печати
    'print-media-type': None,  # Использовать CSS для печати
    'zoom': 1.3,  # Масштабирование
    'javascript-delay': 1000,  # Задержка для выполнения JS
    'no-stop-slow-scripts': None,  # Не останавливать медленные скрипты
    'debug-javascript': None,  # Отладка JavaScript
    'load-error-handling': 'ignore',  # Игнорировать ошибки загрузки
    'load-media-error-handling': 'ignore'
}

Работа с заголовками и колонтитулами

options = {
    'header-html': 'header.html',
    'footer-html': 'footer.html',
    'header-spacing': 5,
    'footer-spacing': 5,
    'header-font-size': 8,
    'footer-font-size': 8
}

Интеграция с веб-фреймворками

Flask

from flask import Flask, render_template, Response
import pdfkit

app = Flask(__name__)

@app.route('/generate-pdf')
def generate_pdf():
    # Рендерим HTML-шаблон
    html = render_template('invoice.html', 
                          customer_name='Иван Петров',
                          amount=15000)
    
    # Конвертируем в PDF
    pdf = pdfkit.from_string(html, False)
    
    return Response(pdf, 
                   mimetype='application/pdf',
                   headers={'Content-Disposition': 'attachment; filename=invoice.pdf'})

Django

from django.http import HttpResponse
from django.template.loader import render_to_string
import pdfkit

def generate_report(request):
    # Подготавливаем контекст
    context = {
        'title': 'Отчёт за месяц',
        'data': get_report_data(),
        'date': datetime.now()
    }
    
    # Рендерим шаблон
    html = render_to_string('report_template.html', context)
    
    # Создаём PDF
    pdf = pdfkit.from_string(html, False, options={
        'page-size': 'A4',
        'margin-top': '1in',
        'encoding': 'UTF-8'
    })
    
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="report.pdf"'
    return response

FastAPI

from fastapi import FastAPI
from fastapi.responses import Response
import pdfkit

app = FastAPI()

@app.post("/generate-pdf")
async def create_pdf(html_content: str):
    options = {
        'page-size': 'A4',
        'margin-top': '0.75in',
        'encoding': "UTF-8",
    }
    
    pdf = pdfkit.from_string(html_content, False, options=options)
    
    return Response(
        content=pdf,
        media_type='application/pdf',
        headers={'Content-Disposition': 'attachment; filename=document.pdf'}
    )

Полная таблица методов и параметров

Метод Описание Параметры
pdfkit.from_url(url, output_path, options=None, configuration=None) Конвертирует веб-страницу в PDF url: адрес страницы
output_path: путь к файлу или False для bytes
pdfkit.from_file(input, output_path, options=None, configuration=None) Конвертирует HTML-файл в PDF input: путь к HTML-файлу
output_path: путь к выходному файлу
pdfkit.from_string(string, output_path, options=None, configuration=None) Конвертирует HTML-строку в PDF string: HTML-содержимое
output_path: путь к файлу или False
pdfkit.configuration(wkhtmltopdf=None) Настройка пути к исполняемому файлу wkhtmltopdf: полный путь к бинарнику

Основные опции конфигурации

Параметр Описание Возможные значения
page-size Размер страницы A4, A3, Letter, Legal, Tabloid
orientation Ориентация страницы Portrait, Landscape
margin-top/bottom/left/right Отступы Значения в in, cm, mm, px
encoding Кодировка текста UTF-8, Windows-1251, etc.
dpi Разрешение для печати 72, 150, 300, 600
zoom Масштаб страницы 0.1 - 3.0
print-media-type Использовать CSS для печати None (для активации)
javascript-delay Задержка выполнения JS (мс) 0-10000
no-outline Отключить оглавление None
grayscale Чёрно-белый режим None

Работа с CSS и стилями

Оптимизация для печати

Создавайте специальные CSS-стили для PDF:

@media print {
    body { 
        font-family: 'DejaVu Sans', sans-serif;
        font-size: 12pt;
        line-height: 1.4;
    }
    
    .no-print { display: none; }
    
    .page-break { 
        page-break-before: always; 
    }
    
    table { 
        page-break-inside: avoid; 
    }
}

Подключение внешних шрифтов

<head>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Roboto', sans-serif;
        }
    </style>
</head>

Обработка ошибок и отладка

Типичные проблемы и решения

Ошибка "wkhtmltopdf not found"

import pdfkit

try:
    pdf = pdfkit.from_string(html, False)
except OSError as e:
    if "wkhtmltopdf" in str(e):
        # Указать путь к исполняемому файлу
        config = pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf')
        pdf = pdfkit.from_string(html, False, configuration=config)

Проблемы с кодировкой

options = {
    'encoding': 'UTF-8',
    'enable-local-file-access': None,
    'page-size': 'A4'
}

Отладка JavaScript

debug_options = {
    'debug-javascript': None,
    'javascript-delay': 2000,
    'no-stop-slow-scripts': None
}

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

Кэширование конфигурации

# Создаём конфигурацию один раз
config = pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf')
options = {
    'page-size': 'A4',
    'encoding': 'UTF-8',
    'margin-top': '0.75in'
}

# Используем повторно
pdf1 = pdfkit.from_string(html1, False, options=options, configuration=config)
pdf2 = pdfkit.from_string(html2, False, options=options, configuration=config)

Асинхронная обработка

import asyncio
import concurrent.futures

async def generate_pdf_async(html_content, options):
    loop = asyncio.get_event_loop()
    with concurrent.futures.ThreadPoolExecutor() as executor:
        pdf = await loop.run_in_executor(
            executor, 
            pdfkit.from_string, 
            html_content, 
            False, 
            options
        )
    return pdf

Использование в различных окружениях

Docker-контейнеры

FROM python:3.9

# Установка wkhtmltopdf
RUN apt-get update && apt-get install -y \
    wkhtmltopdf \
    xvfb \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install -r requirements.txt

# Для headless-режима
ENV DISPLAY=:0

AWS Lambda

Для использования в AWS Lambda потребуется специальная Lambda Layer с wkhtmltopdf:

import os
import pdfkit

# В Lambda-функции
def lambda_handler(event, context):
    # Настройка для Lambda
    config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf')
    
    # Установка переменных окружения
    os.environ['FONTCONFIG_PATH'] = '/opt/fonts'
    os.environ['LD_LIBRARY_PATH'] = '/opt/lib'
    
    pdf = pdfkit.from_string(html, False, configuration=config)
    
    return {
        'statusCode': 200,
        'body': base64.b64encode(pdf).decode('utf-8'),
        'isBase64Encoded': True,
        'headers': {
            'Content-Type': 'application/pdf'
        }
    }

Часто задаваемые вопросы

Как добавить нумерацию страниц?

<style>
@page {
    @bottom-right {
        content: "Страница " counter(page) " из " counter(pages);
    }
}
</style>

Можно ли добавить водяные знаки?

Да, используя CSS:

body::before {
    content: "КОНФИДЕНЦИАЛЬНО";
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(-45deg);
    font-size: 80px;
    color: rgba(255, 0, 0, 0.1);
    z-index: 9999;
    pointer-events: none;
}

Как обеспечить разрыв страниц?

.page-break {
    page-break-before: always;
}

.avoid-break {
    page-break-inside: avoid;
}

Поддерживаются ли диаграммы и графики?

Да, через SVG, Canvas или библиотеки типа Chart.js с задержкой JavaScript:

options = {
    'javascript-delay': 3000,  # Ждём 3 секунды для отрисовки
    'no-stop-slow-scripts': None
}

Альтернативы PDFKit

WeasyPrint

  • Не требует внешних зависимостей
  • Лучше поддерживает CSS
  • Медленнее PDFKit

ReportLab

  • Программное создание PDF
  • Больше контроля над макетом
  • Сложнее в использовании

xhtml2pdf

  • Чистый Python
  • Ограниченная поддержка CSS
  • Подходит для простых документов

Playwright PDF

  • Современная альтернатива
  • Лучше поддерживает JavaScript
  • Больше потребляет ресурсов

Заключение

PDFKit представляет собой мощный и гибкий инструмент для создания PDF-документов из HTML в Python. Его главные преимущества — простота использования, отличная поддержка современных веб-стандартов и возможность создавать профессиональные документы с минимальными усилиями.

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

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

Новости