Форум программистов, компьютерный форум, киберфорум
py-thonny
Войти
Регистрация
Восстановить пароль

Python и PDF: Создание и редактирование файлов

Запись от py-thonny размещена 20.03.2025 в 09:25
Показов 1404 Комментарии 0
Метки pdf, python

Нажмите на изображение для увеличения
Название: 2750f750-1499-4fbd-92b1-52ed9b806335.jpg
Просмотров: 50
Размер:	187.5 Кб
ID:	10471
Работа с PDF-документами – одна из популярных задач в современной разработке. Python предлагает несколько инструментов для создания, чтения и редактирования PDF-файлов, среди которых особенно выделяются библиотеки pypdf и ReportLab, каждая со своими сильными сторонами.

Библиотека pypdf – современное решение для манипуляций с существующими PDF-файлами. Она позволяет извлекать текст, объединять документы, поворачивать страницы и даже шифровать файлы. При этом библиотека не требует установки дополнительных зависимостей, что упрощает её интеграцию в проекты. ReportLab специализируется на создании PDF с нуля. С её помощью можно генерировать сложные документы, включающие таблицы, графики и различные шрифты. ReportLab широко применяется в бизнес-приложениях для автоматической генерации отчётов и документации.

Выбор между этими библиотеками зависит от конкретной задачи. Если нужно работать с готовыми PDF – pypdf станет отличным выбором. Когда требуется создавать новые документы с богатым форматированием – ReportLab окажется незаменимым инструментом. Стоит отметить особенности работы с PDF в Python. В отличие от текстовых форматов, PDF имеет сложную внутреннюю структуру. Это может создавать определённые сложности при извлечении текста или изображений. Например, текст может быть представлен как набор отдельных символов с координатами, а не как последовательный поток данных. Производительность также играет важную роль. При обработке больших PDF-файлов или массовой генерации документов нужно учитывать затраты памяти и времени выполнения. В таких случаях часто применяют потоковую обработку или распараллеливание задач.

Создание PDF с нуля



ReportLab - пожалуй, лучший инструмент для программной генерации PDF-документов на Python. В отличие от других библиотек, он позволяет создавать файлы с чистого листа и полностью контролировать их содержимое и оформление. Начнём с установки библиотеки через pip:

Python
1
pip install reportlab
Центральный элемент в работе с 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 файлов
Уважаемые подскажите пожалуйста, в чем ошибка. Взял с учебника &quot;решение рутинных задач...&quot; дополнил иначе вообще не работало, по итогу...

Считывание pdf - файлов
Нашел в интернете пакет для работы с pdf - файлами PDFMiner, вот пример работы: import io from pdfminer.converter import TextConverter ...

Можно ли в Python подписать документ pdf электронной подписью?
Необходимо при наличии документа .pdf и ЭЦП допустим .cer получить на выходе подписанный pdf, с помощью каких инструментов это возможно сделать,...

Полный Курс SICP в MIT-е на Python существует в PDF?
Всем привет. Такой вопрос. Хочу найти курс СИКП на питоне , аналогичный старому курсу на лиспе. Все что находил в pdf там где то 250 - 350 стр...

Сортировка данных из pdf файлов
Доброго времени суток, форумчане! Перейду сразу к сути вопроса. Есть большой перечень пдф файлов вроде закрепленного. В них хранятся сведения о...

Метки pdf, python
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Обнаружение объектов в реальном времени на Python с YOLO и OpenCV
AI_Generated 29.04.2025
Компьютерное зрение — одна из самых динамично развивающихся областей искусственного интеллекта. В нашем мире, где визуальная информация стала доминирующим способом коммуникации, способность машин. . .
Эффективные парсеры и токенизаторы строк на C#
UnmanagedCoder 29.04.2025
Обработка текстовых данных — частая задача в программировании, с которой сталкивается почти каждый разработчик. Парсеры и токенизаторы составляют основу множества современных приложений: от. . .
C++ в XXI веке - Эволюция языка и взгляд Бьярне Страуструпа
bytestream 29.04.2025
C++ существует уже более 45 лет с момента его первоначальной концепции. Как и было задумано, он эволюционировал, отвечая на новые вызовы, но многие разработчики продолжают использовать C++ так, будто. . .
Слабые указатели в Go: управление памятью и предотвращение утечек ресурсов
golander 29.04.2025
Управление памятью — один из краеугольных камней разработки высоконагруженных приложений. Го (Go) занимает уникальную нишу в этом вопросе, предоставляя разработчикам автоматическое управление памятью. . .
Разработка кастомных расширений для компилятора C++
NullReferenced 29.04.2025
Создание кастомных расширений для компиляторов C++ — инструмент оптимизации кода, внедрения новых языковых функций и автоматизации задач. Многие разработчики недооценивают гибкость современных. . .
Гайд по обработке исключений в C#
stackOverflow 29.04.2025
Разработка надёжного программного обеспечения невозможна без грамотной обработки исключительных ситуаций. Любая программа, независимо от её размера и сложности, может столкнуться с непредвиденными. . .
Создаем RESTful API с Laravel
Jason-Webb 28.04.2025
REST (Representational State Transfer) — это архитектурный стиль, который определяет набор принципов для создания веб-сервисов. Этот подход к построению API стал стандартом де-факто в современной. . .
Дженерики в C# - продвинутые техники
stackOverflow 28.04.2025
История дженериков началась с простой идеи — создать механизм для разработки типобезопасного кода без потери производительности. До их появления программисты использовали неуклюжие преобразования. . .
Тестирование в Python: PyTest, Mock и лучшие практики TDD
py-thonny 28.04.2025
Тестирование кода играет весомую роль в жизненном цикле разработки программного обеспечения. Для разработчиков Python существует богатый выбор инструментов, позволяющих создавать надёжные и. . .
Работа с PDF в Java с iText
Javaican 28.04.2025
Среди всех форматов PDF (Portable Document Format) заслуженно занимает особое место. Этот формат, созданный компанией Adobe, превратился в универсальный стандарт для обмена документами, не зависящий. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru