Работа с PDF-документами – одна из популярных задач в современной разработке. Python предлагает несколько инструментов для создания, чтения и редактирования PDF-файлов, среди которых особенно выделяются библиотеки pypdf и ReportLab, каждая со своими сильными сторонами.
Библиотека pypdf – современное решение для манипуляций с существующими PDF-файлами. Она позволяет извлекать текст, объединять документы, поворачивать страницы и даже шифровать файлы. При этом библиотека не требует установки дополнительных зависимостей, что упрощает её интеграцию в проекты. ReportLab специализируется на создании PDF с нуля. С её помощью можно генерировать сложные документы, включающие таблицы, графики и различные шрифты. ReportLab широко применяется в бизнес-приложениях для автоматической генерации отчётов и документации.
Выбор между этими библиотеками зависит от конкретной задачи. Если нужно работать с готовыми PDF – pypdf станет отличным выбором. Когда требуется создавать новые документы с богатым форматированием – ReportLab окажется незаменимым инструментом. Стоит отметить особенности работы с PDF в Python. В отличие от текстовых форматов, PDF имеет сложную внутреннюю структуру. Это может создавать определённые сложности при извлечении текста или изображений. Например, текст может быть представлен как набор отдельных символов с координатами, а не как последовательный поток данных. Производительность также играет важную роль. При обработке больших PDF-файлов или массовой генерации документов нужно учитывать затраты памяти и времени выполнения. В таких случаях часто применяют потоковую обработку или распараллеливание задач.
Создание PDF с нуля
ReportLab - пожалуй, лучший инструмент для программной генерации PDF-документов на Python. В отличие от других библиотек, он позволяет создавать файлы с чистого листа и полностью контролировать их содержимое и оформление. Начнём с установки библиотеки через pip:
Центральный элемент в работе с ReportLab - класс Canvas, который представляет собой холст для рисования. Создадим простой документ:
Python | 1
2
3
4
5
6
7
| from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm
canvas = Canvas("hello.pdf", pagesize=A4)
canvas.drawString(2*cm, 29*cm, "Привет, PDF!")
canvas.save() |
|
ReportLab использует систему координат, где точка отсчёта находится в левом нижнем углу страницы. Координаты задаются в пунктах (1/72 дюйма), но для удобства можно использовать сантиметры или дюймы через специальные константы.
Шрифты - важный аспект оформления документов. ReportLab поддерживает встроенные шрифты и позволяет подключать пользовательские:
Python | 1
2
3
4
5
| from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont('Arial', 'arial.ttf'))
canvas.setFont('Arial', 14) |
|
При работе со шрифтами нужно учитывать проблемы с кодировкой. Не все шрифты поддерживают кириллицу или специальные символы. Тестирование на реальных данных поможет избежать неприятных сюрпризов.
Для создания сложных документов удобно использовать высокоуровневые компоненты ReportLab. Например, Platypus предоставляет классы для работы с абзацами, таблицами и изображениями:
Python | 1
2
3
4
5
6
7
8
9
10
| from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
doc = SimpleDocTemplate("complex.pdf")
styles = getSampleStyleSheet()
story = []
text = "Этот абзац автоматически переносится на новую строку при достижении края страницы"
story.append(Paragraph(text, styles['Normal']))
doc.build(story) |
|
При генерации больших документов важно следить за потреблением памяти. Platypus использует концепцию "истории" - списка элементов, которые последовательно добавляются в документ. Это позволяет обрабатывать большие объёмы данных без загрузки всего содержимого в память.
ReportLab также поддерживает создание таблиц. Можно настраивать границы, цвета фона, объединять ячейки:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| from reportlab.platypus import Table
from reportlab.lib import colors
data = [['Год', 'Доход', 'Расход'],
['2022', '100000', '80000'],
['2023', '120000', '90000']]
table = Table(data)
table.setStyle([
('GRID', (0,0), (-1,-1), 1, colors.black),
('BACKGROUND', (0,0), (-1,0), colors.grey)
])
story.append(table) |
|
Для динамической генерации контента можно использовать условное форматирование. Например, выделять отрицательные значения красным цветом или менять размер шрифта в зависимости от длины текста.
Важный нюанс - обработка ошибок. ReportLab может выбрасывать исключения при неверных входных данных или проблемах с шрифтами. Хорошей практикой будет оборачивать код генерации PDF в try-except блоки и логировать ошибки:
Python | 1
2
3
4
5
| try:
doc.build(story)
except Exception as e:
logging.error(f"Ошибка при создании PDF: {str(e)}")
raise |
|
При работе с изображениями нужно проверять их размеры и формат. ReportLab поддерживает JPEG, PNG и GIF, но может некорректно обрабатывать слишком большие файлы или экзотические форматы.
ReportLab предоставляет широкие возможности для создания графиков и диаграмм. Библиотека включает модуль graphics, который позволяет рисовать линии, фигуры и строить графики:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.graphics import renderPDF
drawing = Drawing(400, 200)
data = [(1, 2), (2, 3), (3, 5), (4, 6)]
lp = LinePlot()
lp.x = 50
lp.y = 50
lp.width = 300
lp.height = 125
lp.data = [data]
drawing.add(lp)
renderPDF.draw(drawing, canvas, 100, 400) |
|
При создании сложных документов часто требуется автоматическая нумерация страниц и оглавление. Для этого можно использовать специальные методы Canvas:
Python | 1
2
3
4
5
6
7
8
9
10
11
| def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Roman', 10)
page_num = canvas.getPageNumber()
text = f"Страница {page_num}"
canvas.drawRightString(200*mm, 20*mm, text)
canvas.restoreState()
doc = SimpleDocTemplate("document.pdf",
pagesize=A4,
onPageEnd=add_page_number) |
|
Для создания интерактивных элементов ReportLab поддерживает гиперссылки и закладки:
Python | 1
2
3
| canvas.linkURL("https://example.com", (100, 100, 200, 120), relative=1)
canvas.bookmarkPage("section1")
canvas.addOutlineEntry("Раздел 1", "section1", 0) |
|
При работе с большими таблицами может потребоваться автоматический перенос на новую страницу. Platypus автоматически обрабатывает такие ситуации, но иногда нужна тонкая настройка:
Python | 1
2
| table = Table(data, repeatRows=1) # Повторять заголовок на каждой странице
table.keepWithNext = True # Не разрывать с следующим элементом |
|
Важная вещь - оптимизация размера PDF-файлов. Можно сжимать изображения и использовать встроенные шрифты только для нужных символов:
Python | 1
2
3
4
5
6
7
8
9
10
| from reportlab.lib.utils import ImageReader
from PIL import Image
import io
def optimize_image(image_path, max_size=(800, 800)):
img = Image.open(image_path)
img.thumbnail(max_size)
buf = io.BytesIO()
img.save(buf, format='JPEG', quality=85)
return ImageReader(buf) |
|
При создании форм ReportLab позволяет добавлять различные поля ввода:
Python | 1
2
3
4
5
6
7
8
9
| from reportlab.pdfbase.acroform import AcroForm
canvas.acroForm = AcroForm(canvas)
canvas.acroForm.textfield(
name='username',
tooltip='Введите имя',
x=100, y=500,
width=200, height=20
) |
|
Для защиты документов можно установить пароли и ограничения:
Python | 1
2
3
4
5
| canvas.setEncrypt('user_pwd', 'owner_pwd',
canPrint=0,
canModify=0,
canCopy=0,
canAnnotate=0) |
|
При работе с нестандартными макетами может пригодиться система фреймов:
Python | 1
2
3
4
5
6
7
8
| from reportlab.platypus.frames import Frame
main_frame = Frame(
x1=cm, y1=cm,
width=A4[0]-2*cm,
height=A4[1]-2*cm,
showBoundary=1
) |
|
Для создания профессиональных документов часто требуется добавление колонтитулов и водяных знаков:
Python | 1
2
3
4
5
6
7
| def watermark(canvas, doc):
canvas.saveState()
canvas.setFillColorRGB(0.9, 0.9, 0.9)
canvas.setFont("Helvetica", 70)
canvas.rotate(45)
canvas.drawString(100, 100, "ЧЕРНОВИК")
canvas.restoreState() |
|
При генерации документов на основе данных важно учитывать возможные проблемы с кодировками и специальными символами. Хорошей практикой будет предварительная очистка и валидация данных:
Python | 1
2
3
4
5
6
7
| def clean_text(text):
# Заменяем проблемные символы
text = text.replace('\x00', '')
# Проверяем длину строк
if len(text) > 1000:
text = text[:997] + '...'
return text |
|
Создание и редактирование web содержимого на Python Добрый день,
Не знаю в какую сторону копать гранит науки, подскажите. Мне нужно, чтоб html страница на одном компьютере обрабатывала локальные... Python convert PDF Редактируемую форму PDF конвертировать в печатную форму PDF. Python работа с PDF приобразовываем PDF в байты
with open("pdf-test.pdf", "rb") as image:
f = image.read()
b = bytearray(f)
print(b)
... Python pyqt5 view pdf Здраствуйте!
Есть задача: нужно создать приложение, которое, просто, отображает пдф из файла. Тоесть, я указываю адрес к пдф-файлу и в...
Манипуляции с существующими PDF
Библиотека pypdf открывает широкие возможности для работы с существующими PDF-файлами. От простого чтения до сложных манипуляций со страницами - всё это доступно через удобный программный интерфейс. Начнем с базовых операций. Для чтения PDF используется класс PdfReader:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| from pypdf import PdfReader
from pathlib import Path
pdf_path = Path("document.pdf")
reader = PdfReader(pdf_path)
# Получаем количество страниц
page_count = len(reader.pages)
# Читаем метаданные
metadata = reader.metadata
print(f"Автор: {metadata.author}")
print(f"Заголовок: {metadata.title}") |
|
Извлечение текста - одна из самых частых задач. Каждая страница PDF представлена объектом PageObject, который предоставляет метод extract_text():
Python | 1
2
3
4
5
6
7
8
9
|
# Извлекаем текст с первой страницы
first_page = reader.pages[0]
text = first_page.extract_text()
# Извлекаем текст со всех страниц
all_text = ""
for page in reader.pages:
all_text += page.extract_text() |
|
При работе с текстом нужно учитывать особенности форматирования PDF. Текст может быть разбит на колонки или иметь сложную структуру, что затрудняет его извлечение. В таких случаях может потребоваться дополнительная обработка:
Python | 1
2
3
4
5
6
| def clean_extracted_text(text):
# Убираем лишние переносы строк
text = ' '.join(text.split())
# Заменяем множественные пробелы
text = ' '.join(text.split())
return text |
|
Для записи изменений используется класс PdfWriter. С его помощью можно создавать новые документы на основе существующих:
Python | 1
2
3
4
5
6
7
8
9
10
| from pypdf import PdfWriter
writer = PdfWriter()
# Копируем страницы из исходного документа
for page in reader.pages:
writer.add_page(page)
# Сохраняем результат
with open("output.pdf", "wb") as output:
writer.write(output) |
|
Часто требуется объединить несколько PDF-файлов. Для этого можно использовать класс PdfMerger:
Python | 1
2
3
4
5
6
7
8
9
10
| from pypdf import PdfMerger
merger = PdfMerger()
files = ["file1.pdf", "file2.pdf", "file3.pdf"]
for pdf in files:
merger.append(pdf)
merger.write("merged.pdf")
merger.close() |
|
При слиянии документов можно указать диапазон страниц и их порядок:
Python | 1
2
3
4
5
| # Добавляем страницы с 2 по 5 из первого файла
merger.append("file1.pdf", pages=[1,2,3,4])
# Вставляем страницы в определённую позицию
merger.merge(2, "file2.pdf") |
|
Поворот страниц - ещё одна распространённая операция. Каждая страница может быть повёрнута на произвольный угол, кратный 90 градусам:
Python | 1
2
3
4
5
6
| # Поворачиваем первую страницу на 90 градусов
page = reader.pages[0]
page.rotate(90)
# Проверяем текущий угол поворота
current_rotation = page.rotation |
|
Для работы с формами PDF библиотека предоставляет специальные методы:
Python | 1
2
3
4
5
6
7
8
| # Получаем список полей формы
fields = reader.get_fields()
# Заполняем поля в новом документе
writer.update_page_form_field_values(
writer.pages[0],
{"name": "John", "age": "30"}
) |
|
При обработке больших файлов важно учитывать потребление памяти. Можно использовать потоковую обработку страниц:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| def process_large_pdf(input_path, output_path):
reader = PdfReader(input_path)
writer = PdfWriter()
for page in reader.pages:
# Обрабатываем страницу
process_page(page)
# Сразу добавляем в выходной файл
writer.add_page(page)
# Очищаем память
page = None
writer.write(output_path) |
|
Шифрование и защита документов также поддерживаются:
Python | 1
2
3
4
5
6
7
8
| # Шифруем документ
writer.encrypt(user_pwd="user123",
owner_pwd="admin123",
use_128bit=True)
# Проверяем защищённый документ
if reader.is_encrypted:
reader.decrypt("user123") |
|
При работе с изображениями в PDF нужно учитывать их формат и качество:
Python | 1
2
3
4
5
6
7
8
| def extract_images(page):
images = []
for image in page.images:
# Проверяем формат
if image.format in ['JPEG', 'PNG']:
# Сохраняем изображение
images.append(image.data)
return images |
|
Библиотека также позволяет добавлять и редактировать закладки:
Python | 1
2
3
4
5
6
7
8
9
| # Добавляем закладку
writer.add_outline_item(
"Глава 1",
page_number=0,
parent=None
)
# Получаем структуру закладок
outline = reader.outline |
|
При манипуляциях с PDF важно помнить о возможных ошибках и обрабатывать их корректно:
Python | 1
2
3
4
5
6
7
8
| try:
reader = PdfReader(pdf_path)
except FileNotFoundError:
print("Файл не найден")
except PermissionError:
print("Нет доступа к файлу")
except Exception as e:
print(f"Ошибка при чтении PDF: {str(e)}") |
|
Для массовой обработки PDF часто требуется оптимизировать размер файлов. Это особенно актуально при работе с отсканированными документами или файлами, содержащими изображения. pypdf предоставляет инструменты для сжатия:
Python | 1
2
3
4
5
6
7
8
9
| def compress_pdf(input_path, output_path):
reader = PdfReader(input_path)
writer = PdfWriter()
for page in reader.pages:
page.compress_content_streams() # Сжимаем потоки данных
writer.add_page(page)
writer.write(output_path) |
|
При работе с большими коллекциями PDF эффективно использовать асинхронную обработку:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| import asyncio
from pathlib import Path
async def process_pdf(pdf_path):
reader = PdfReader(pdf_path)
# Выполняем длительную обработку
return len(reader.pages)
async def batch_process(pdf_dir):
pdf_files = Path(pdf_dir).glob('*.pdf')
tasks = [process_pdf(pdf) for pdf in pdf_files]
results = await asyncio.gather(*tasks)
return results |
|
Извлечение и анализ изображений часто требует дополнительной обработки. Не все изображения в PDF хранятся в стандартных форматах:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| def extract_image_data(page):
images = []
for image in page.images:
try:
# Проверяем качество изображения
if image.bits_per_component < 8:
continue
# Сохраняем метаданные
meta = {
'width': image.width,
'height': image.height,
'format': image.format,
'size': len(image.data)
}
images.append((image.data, meta))
except Exception as e:
print(f"Ошибка при обработке изображения: {e}")
return images |
|
Добавление водяных знаков и штампов требует точного позиционирования на странице:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
| def add_watermark(page, text, opacity=0.5):
# Создаём новый слой для водяного знака
watermark = PageObject.create_blank_page(
width=page.mediabox.width,
height=page.mediabox.height
)
# Добавляем текст
watermark.merge_page(page)
watermark.transparency = opacity
return watermark |
|
При работе с метаданными PDF важно учитывать различные форматы дат и кодировок:
Python | 1
2
3
4
5
6
7
8
9
10
11
| from datetime import datetime
def parse_pdf_date(date_string):
# PDF даты имеют формат 'D:YYYYMMDDHHmmSS'
if date_string.startswith('D:'):
date_string = date_string[2:]
try:
return datetime.strptime(date_string[:14], '%Y%m%d%H%M%S')
except ValueError:
return None
return None |
|
Для работы с закладками и структурой документа pypdf предоставляет удобный интерфейс:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def build_outline(writer, structure):
"""
structure = [
('Глава 1', 0),
('Раздел 1.1', 1, True), # True = развернуть
]
"""
for item in structure:
title, page, *options = item
writer.add_outline_item(
title,
page_number=page,
expand=options[0] if options else False
) |
|
При обработке форм важно правильно работать с различными типами полей:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
| def process_form_fields(reader):
fields = reader.get_fields()
processed = {}
for key, field in fields.items():
field_type = field.get('/FT', '')
if field_type == '/Tx': # Текстовое поле
processed[key] = field.get('/V', '')
elif field_type == '/Btn': # Чекбокс или радио
processed[key] = bool(field.get('/V', False))
return processed |
|
При работе с цифровыми подписями нужно учитывать различные форматы и стандарты:
Python | 1
2
3
4
5
6
7
8
9
10
| def verify_signature(reader):
if not reader.is_encrypted:
return False
try:
# Проверяем подпись
sig_obj = reader.get_signatures()[0]
return sig_obj.verify()
except:
return False |
|
Создание оглавления на основе закладок требует рекурсивной обработки:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def create_toc(bookmarks, level=0):
toc = []
for bookmark in bookmarks:
title = bookmark.title
page = bookmark.page_number
# Добавляем элемент с учётом уровня вложенности
toc.append((' ' * level + title, page))
# Рекурсивно обрабатываем вложенные закладки
if bookmark.children:
toc.extend(create_toc(bookmark.children, level + 1))
return toc |
|
Продвинутые техники
Оптическое распознавание текста (OCR) в PDF-документах открывает новые возможности для автоматизации. С помощью библиотеки pytesseract можно извлекать текст из отсканированных документов:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| import pytesseract
from pdf2image import convert_from_path
from PIL import Image
def extract_text_from_scanned_pdf(pdf_path):
# Конвертируем PDF в изображения
images = convert_from_path(pdf_path)
text = ""
for image in images:
# Распознаём текст с каждой страницы
text += pytesseract.image_to_string(image, lang='rus')
return text |
|
При работе с OCR важно предварительно обработать изображения для улучшения качества распознавания:
Python | 1
2
3
4
5
| def preprocess_image(image):
# Преобразуем в оттенки серого
gray = image.convert('L')
# Увеличиваем контрастность
return gray.point(lambda x: 0 if x<128 else 255, '1') |
|
Асинхронная обработка больших коллекций PDF требует грамотного управления ресурсами. Вот пример с использованием asyncio и aiofiles:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| import asyncio
import aiofiles
from pypdf import PdfReader, PdfWriter
async def process_pdf_async(input_path, output_path):
async with aiofiles.open(input_path, 'rb') as file:
content = await file.read()
reader = PdfReader(BytesIO(content))
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
async with aiofiles.open(output_path, 'wb') as output:
await output.write(writer.write_bytes())
async def batch_process_pdfs(input_dir):
tasks = []
for pdf_path in Path(input_dir).glob('*.pdf'):
output_path = pdf_path.with_name(f'processed_{pdf_path.name}')
tasks.append(process_pdf_async(pdf_path, output_path))
await asyncio.gather(*tasks) |
|
Защита документов может включать не только пароли, но и цифровые подписи. Для работы с ними используется библиотека pyPdf:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
def sign_pdf(pdf_path, key_path, cert_path):
with open(key_path, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None
)
writer = PdfWriter()
reader = PdfReader(pdf_path)
for page in reader.pages:
writer.add_page(page)
# Добавляем поле для подписи
writer.add_unsigned_signature(
cert=cert_path,
location='Moscow',
reason='Document approval'
) |
|
Создание интерактивных форм требует особого внимания к деталям. Можно добавлять различные типы полей и настраивать их поведение:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| def create_interactive_form():
canvas = Canvas("form.pdf")
form = canvas.acroForm
# Текстовое поле с валидацией
form.textfield(
name='email',
tooltip='Введите email',
x=100, y=500,
width=200, height=20,
forceBorder=True,
validate='email'
)
# Выпадающий список
form.choice(
name='category',
tooltip='Выберите категорию',
x=100, y=450,
width=200, height=20,
options=['A', 'B', 'C']
) |
|
Обработка изображений в PDF требует понимания различных форматов и методов сжатия:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| from PIL import Image
import io
def optimize_pdf_images(reader, quality=85):
writer = PdfWriter()
for page in reader.pages:
for image in page.images:
# Конвертируем в JPEG с оптимальным сжатием
img = Image.open(io.BytesIO(image.data))
output = io.BytesIO()
img.save(output, format='JPEG', quality=quality)
# Заменяем оригинальное изображение
image.data = output.getvalue()
writer.add_page(page)
return writer |
|
Конвертация между форматами часто требуется в корпоративных системах. Можно автоматизировать преобразование различных форматов в PDF:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| from docx2pdf import convert
from pandas import ExcelWriter
import win32com.client
def batch_convert_to_pdf(input_dir):
for file_path in Path(input_dir).glob('*.*'):
if file_path.suffix == '.docx':
convert(file_path, file_path.with_suffix('.pdf'))
elif file_path.suffix == '.xlsx':
excel = win32com.client.Dispatch('Excel.Application')
wb = excel.Workbooks.Open(str(file_path))
wb.ExportAsFixedFormat(0, str(file_path.with_suffix('.pdf')))
wb.Close() |
|
Нестандартные случаи использования включают создание PDF с внедрёнными файлами:
Python | 1
2
3
4
5
6
7
8
9
10
| def embed_files_in_pdf(pdf_path, files_to_embed):
writer = PdfWriter()
reader = PdfReader(pdf_path)
for page in reader.pages:
writer.add_page(page)
for file_path in files_to_embed:
with open(file_path, 'rb') as file:
writer.add_attachment(file_path.name, file.read()) |
|
При работе с большими документами важно оптимизировать использование памяти:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| def process_large_pdf_in_chunks(pdf_path, chunk_size=10):
reader = PdfReader(pdf_path)
total_pages = len(reader.pages)
for start in range(0, total_pages, chunk_size):
end = min(start + chunk_size, total_pages)
writer = PdfWriter()
for i in range(start, end):
writer.add_page(reader.pages[i])
output_path = f'chunk_{start}-{end}.pdf'
writer.write(output_path) |
|
Для защиты конфиденциальных данных в PDF можно использовать различные методы шифрования и управления правами доступа:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| from cryptography.fernet import Fernet
import base64
def encrypt_pdf_content(pdf_path, key):
# Генерируем ключ шифрования
f = Fernet(key)
with open(pdf_path, 'rb') as file:
data = file.read()
# Шифруем содержимое
encrypted_data = f.encrypt(data)
with open('encrypted.pdf', 'wb') as file:
file.write(encrypted_data) |
|
При работе с метаданными PDF важно обеспечить их корректное извлечение и обработку:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| def extract_metadata_safely(reader):
metadata = {}
try:
if reader.metadata:
for key in reader.metadata:
try:
value = reader.metadata[key]
if isinstance(value, bytes):
value = value.decode('utf-8', errors='ignore')
metadata[key] = value
except Exception:
continue
except Exception as e:
print(f"Ошибка при извлечении метаданных: {e}")
return metadata |
|
Для создания сложных макетов можно использовать систему слоев:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
| def create_layered_pdf():
canvas = Canvas("layered.pdf")
# Создаем слои
canvas.beginLayer("background")
canvas.setFillColorRGB(0.9, 0.9, 0.9)
canvas.rect(0, 0, 595, 842, fill=True)
canvas.endLayer()
canvas.beginLayer("content")
canvas.setFillColorRGB(0, 0, 0)
canvas.drawString(100, 700, "Текст на переднем плане")
canvas.endLayer() |
|
При массовой обработке PDF важно правильно управлять ресурсами:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| import contextlib
from typing import Iterator, Any
@contextlib.contextmanager
def pdf_processor(path: str) -> Iterator[Any]:
reader = None
try:
reader = PdfReader(path)
yield reader
finally:
if reader:
reader.stream.close()
def batch_process_pdfs(paths: list[str]) -> None:
for path in paths:
with pdf_processor(path) as reader:
process_single_pdf(reader) |
|
Для работы с табличными данными можно использовать специализированные функции:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| def extract_tables(page):
# Определяем границы таблицы
tables = []
current_table = []
text_objects = page.extract_text_objects()
for obj in text_objects:
if is_table_cell(obj):
current_table.append(obj)
elif current_table:
tables.append(process_table(current_table))
current_table = []
return tables
def is_table_cell(text_obj):
# Эвристики для определения ячейки таблицы
x, y, width, height = text_obj.bbox
return width < 200 and height < 50 |
|
Для создания PDF с векторной графикой:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| from reportlab.graphics.shapes import Path, Drawing
from reportlab.graphics import renderPDF
def create_vector_graphics():
d = Drawing(400, 200)
# Создаем сложный путь
p = Path()
p.moveTo(10, 10)
p.lineTo(10, 190)
p.curveTo(110, 190, 110, 10, 210, 10)
p.closePath()
d.add(p)
renderPDF.draw(d, canvas, 100, 400) |
|
При работе с формами часто требуется валидация данных:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
| def validate_form_data(form_fields):
errors = []
for field_name, value in form_fields.items():
if field_name.startswith('email'):
if not '@' in value:
errors.append(f"Неверный формат email: {value}")
elif field_name.startswith('phone'):
if not value.replace('+', '').isdigit():
errors.append(f"Неверный формат телефона: {value}")
return errors |
|
Для работы с цифровыми подписями в корпоративной среде:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| def apply_digital_signature(pdf_path, cert_path, reason='Approved'):
writer = PdfWriter()
reader = PdfReader(pdf_path)
# Копируем страницы
for page in reader.pages:
writer.add_page(page)
# Добавляем подпись
writer.add_unsigned_signature(
cert=cert_path,
location='Moscow',
reason=reason,
contact_info='support@company.com'
) |
|
При обработке сканированных документов может потребоваться предварительная обработка изображений:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| from PIL import Image, ImageEnhance, ImageFilter
def enhance_scanned_page(image):
# Повышаем контрастность
enhancer = ImageEnhance.Contrast(image)
image = enhancer.enhance(1.5)
# Убираем шум
image = image.filter(ImageFilter.MedianFilter(size=3))
# Повышаем резкость
image = image.filter(ImageFilter.SHARPEN)
return image |
|
Для оптимизации производительности при работе с большими файлами:
Python | 1
2
3
4
5
6
7
8
9
10
| def process_pdf_streams(reader):
# Используем генератор для экономии памяти
def page_generator():
for page in reader.pages:
processed = process_single_page(page)
yield processed
writer = PdfWriter()
for processed_page in page_generator():
writer.add_page(processed_page) |
|
Кое-какие примеры
Автоматизация документооборота с помощью Python и PDF-библиотек находит широкое применение в реальных проектах. Разработка микросервиса для конвертации и обработки PDF-документов может существенно упростить работу с документами в организации.
Простой FastAPI сервис для работы с PDF:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| from fastapi import FastAPI, UploadFile
from pypdf import PdfReader, PdfWriter
import io
app = FastAPI()
@app.post("/merge")
async def merge_pdfs(files: list[UploadFile]):
merger = PdfMerger()
for file in files:
content = await file.read()
merger.append(io.BytesIO(content))
output = io.BytesIO()
merger.write(output)
merger.close()
return Response(output.getvalue(), media_type="application/pdf") |
|
Массовая персонализация PDF-документов часто требуется для рассылок и отчётов. Python позволяет автоматизировать этот процесс:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| def personalize_documents(template_path, data):
reader = PdfReader(template_path)
for record in data:
writer = PdfWriter()
for page in reader.pages:
# Копируем страницу
writer.add_page(page)
# Заполняем поля данными
writer.update_page_form_field_values(
writer.pages[0],
record
)
# Сохраняем персонализированный документ
output_path = f"document_{record['id']}.pdf"
writer.write(output_path) |
|
Реализация поисковой системы по PDF-библиотеке требует индексации содержимого. Можно использовать векторные базы данных для поиска похожих документов:
Python | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
def index_pdf_library(pdf_dir):
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = []
docs = []
for pdf in Path(pdf_dir).glob('*.pdf'):
reader = PdfReader(pdf)
text = ""
for page in reader.pages:
text += page.extract_text()
embedding = model.encode(text)
embeddings.append(embedding)
docs.append(str(pdf))
index = faiss.IndexFlatL2(len(embeddings[0]))
index.add(np.array(embeddings))
return index, docs |
|
Электронный архив с полнотекстовым поиском можно реализовать, комбинируя PDF-обработку с современными поисковыми движками. При этом важно обеспечить надёжное хранение и быстрый доступ к документам.
Python 3.7 Конвертация PDF в DOCX Приветствую, друзья и коллеги!
Нужна помощь.
Возникла необходимость замены некоторых элементов текста в PDF документах. Знаю про PDFTron... Манипуляций с PDF файлами в Python Как закрыть возможность копирования текста PDF файла? Редактирование скрипта Python Добрый день,
надеюсь найдутся те, кто разбирается как в Python, так и в c++?
У меня было задание написать одинаковый скрипт для с++ и Python.... Открыть pdf, rtf файл через Python Подскажите, пожалуйста, одну вещь:
Пользователь хочет выбрать один из файлов (будь то rtf или pdf). Выбрать и просто открыть этот файл. То есть... Конвертация текста из pdf файла в txt python Здравствуйте, pdf файл без сканов(изображений) хорошо конвертирует.
Собственно вопрос, как мне из моего файла, который забит сканами, получить... Редактирование фрактального дерева на Python Короче суть такова с помощью модуля Turtle я написал код для создания простенького фрактального дерева и мне теперь нужна ваша помощь. Преподаватель... Редактирование файла в python-openpyxl ДД!
пишу тестовый скрипт в robot framework. На сайт импортируются данные из файла .xlsx. Поскольку для каждого запуска скрипта нужны уникальные... Объединение PDF файлов Уважаемые подскажите пожалуйста, в чем ошибка. Взял с учебника "решение рутинных задач..." дополнил иначе вообще не работало, по итогу... Считывание pdf - файлов Нашел в интернете пакет для работы с pdf - файлами PDFMiner, вот пример работы:
import io
from pdfminer.converter import TextConverter ... Можно ли в Python подписать документ pdf электронной подписью? Необходимо при наличии документа .pdf и ЭЦП допустим .cer получить на выходе подписанный pdf, с помощью каких инструментов это возможно сделать,... Полный Курс SICP в MIT-е на Python существует в PDF? Всем привет.
Такой вопрос.
Хочу найти курс СИКП на питоне , аналогичный старому курсу на лиспе.
Все что находил в pdf там где то 250 - 350 стр... Сортировка данных из pdf файлов Доброго времени суток, форумчане! Перейду сразу к сути вопроса. Есть большой перечень пдф файлов вроде закрепленного. В них хранятся сведения о...
|