Что такое 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-документов для различных бизнес-задач.
Настоящее и будущее развития ИИ: классической математики уже недостаточно
Эксперты предупредили о рисках фейковой благотворительности с помощью ИИ
В России разработали универсального ИИ-агента для роботов и индустриальных процессов