【实战】PDF без втрат стиснення: оптимізація структури на основі PyMuPDF
【实战】PDF без втрат стиснення: оптимізація структури на основі PyMuPDF
У повсякденній роботі ми часто стикаємося з проблемою надмірного розміру PDF-файлів: обмеження на розмір вкладень у електронній пошті, повільна швидкість завантаження та скачування, велике використання пам'яті. Традиційні методи стиснення або знижують якість зображень, що призводить до розмиття, або перетворюють текст на зображення, втрачаючи можливість пошуку, що є невиправданим.
Сьогодні я хочу поділитися з вами безвтратним рішенням для стиснення PDF — оптимізацією внутрішньої структури PDF на основі бібліотеки PyMuPDF (fitz), очищенням зайвих даних, що дозволяє ефективно зменшити обсяг файлу, зберігаючи можливість пошуку тексту та візуальну чіткість.
一、核心实现原理
Спочатку наведемо основний код, який є ключовою логікою для оптимізації структури PDF:
import os
from pathlib import Path
import fitz # PyMuPDF
def compress_pdf_simple(input_path, output_path=None):
"""
Простий метод стиснення PDF - лише оптимізація структури (без втрат)
Параметри:
input_path (str): шлях до вхідного PDF файлу
output_path (str): шлях до вихідного PDF файлу
Повертає:
str: шлях до вихідного файлу
"""
try:
# Відкриваємо PDF файл
doc = fitz.open(input_path)
# Інтелектуально генеруємо вихідний шлях (якщо не вказано)
if output_path is None:
input_file = Path(input_path)
output_path = str(input_file.parent / f"{input_file.stem}_simple_compressed{input_file.suffix}")
# Основне: реалізація безвтратного стиснення через комбінацію параметрів
doc.save(
output_path,
garbage=4, # Максимально очищаємо невикористовувані об'єкти
deflate=True, # Використовуємо алгоритм безвтратного стиснення deflate
clean=True, # Очищення/оптимізація внутрішньої структури PDF
pretty=False # Компактний вихід, видалення пробілів
)
# Закриваємо документ для звільнення ресурсів
doc.close()
# Обчислюємо інформацію про стиснення
original_size = os.path.getsize(input_path)
compressed_size = os.path.getsize(output_path)
compression_ratio = (1 - compressed_size / original_size) * 100
# Виводимо результати стиснення
print(f"✅ Просте стиснення завершено!")
print(f"📄 Оригінальний файл: {input_path} ({original_size / 1024 / 1024:.2f} MB)")
print(f"📦 Стиснений файл: {output_path} ({compressed_size / 1024 / 1024:.2f} MB)")
print(f"📉 Коефіцієнт стиснення: {compression_ratio:.1f}%")
print(f"🔍 Збереження можливості пошуку тексту: Так")
return output_path
except Exception as e:
print(f"❌ Під час стиснення виникла помилка: {str(e)}")
return None
# Приклад виклику
# compress_pdf_simple("ваш_файл.pdf")
Цей підхід базується на використанні 4-х ключових параметрів методу save() PyMuPDF, що дозволяє оптимізувати PDF, не змінюючи вміст документа.
二、关键参数深度解析
2.1 garbage=4:精准清理“孤儿”对象
У PDF-файлах є багато непрямих об'єктів (сторінки, шрифти, зображення, коментарі тощо), видалення вмісту під час редагування документа не очищає відразу базові посилання, що призводить до накопичення великої кількості "сирітських об'єктів".
| Значення параметра garbage | Рівень очищення | Сценарії використання |
|---|---|---|
| 0 | Не очищати | Лише швидке збереження, без стиснення |
| 1 | Очищення очевидно невикористовуваних об'єктів | Легке оптимізування, пріоритет на сумісність |
| 2 | Глибока перевірка посилань | Звичайне оптимізування, баланс між ефектом і безпекою |
| 3 | Агресивне очищення | Максимальне стиснення простих PDF-файлів |
| 4 | Максимальне очищення | Документи, що редагувалися кілька разів, потрібно спочатку перевірити цілісність |
Процес дії: перебір усіх непрямих об'єктів → побудова графа посилань → видалення об'єктів без посилань → звільнення пам'яті. Фактичний ефект: документи, що редагувалися кілька разів, можуть зменшити обсяг на 10-30%.
2.2 deflate=True:通用无损压缩算法
deflate — це рекомендований стандартом PDF алгоритм безвтратного стиснення (на основі LZ77 + кодування Хаффмана), з максимальною сумісністю, практично всі PDF-рідери можуть його декодувати.
Після активації буде стиснуто ці об'єкти:
- Потоки вмісту сторінок
- Потоки даних шрифтів
- Потоки даних зображень, які не були стиснуті іншими алгоритмами
2.3 clean=True:优化文档结构
PDF складається з двох частин: "структура документа" та "потоки вмісту", clean=True спеціально оптимізує структурну частину:
- Видалення повторюваних PDF-об'єктів
- Об'єднання посилань на однаковий вміст
- Оптимізація структури дерева сторінок
- Очищення зайвої метаданих
Фактичний ефект: багатосторінкові документи можуть зменшити обсяг на 5-15%.
2.4 pretty=False:紧凑输出
PDF за своєю суттю є бінарним форматом, pretty=True зберігає відступи, переноси рядків та інші пробіли для підвищення читабельності, тоді як pretty=False видаляє всі непотрібні пробіли, ще більше зменшуючи обсяг (допоміжний ефект для вже стиснених файлів deflate, але краще, ніж нічого).
三、完整压缩流程

四、技术难点与解决方案
4.1 压缩率 vs 文档完整性
Виклик: агресивний збір сміття (garbage=4) може пошкодити складні PDF (з скриптами/формами). Рішення:
- Перед стисненням перевірити цілісність документа
- Зашифровані PDF потрібно спочатку розшифрувати, а потім стиснути
- Використовувати try-except для захоплення виключень, щоб уникнути збоїв програми
4.2 保持文本可搜索性
Виклик: деякі методи стиснення можуть перетворити текст на зображення, що ускладнює вибір/пошук. Переваги цього рішення:
- Не змінює вміст тексту та кодування
- Лише оптимізує відносини посилань на об'єкти
- Зберігає цілісність об'єктів шрифтів
- Метод перевірки: тестування функції вибору тексту за допомогою PDF-рідера після стиснення
4.3 大文件内存管理
Виклик: PDF розміром у кілька сотень МБ може призвести до переповнення пам'яті. Рекомендації з оптимізації:
- Обробка надвеликих файлів по сторінках
- Своєчасне закриття об'єкта doc для звільнення ресурсів
- Моніторинг використання пам'яті, використання потокової обробки
4.4 智能生成输出路径
Використання бібліотеки pathlib для автоматичного генерування шляхів, зберігаючи оригінальну назву файлу + мітку стиснення, кросплатформна сумісність:
if output_path is None:
input_file = Path(input_path)
output_path = str(input_file.parent / f"{input_file.stem}_simple_compressed{input_file.suffix}")
五、使用场景与效果预估
5.1 适用场景
- Академічні документи: PDF, завантажені з arXiv, зазвичай містять багато зайвої інформації
- Архівування електронних книг: стиснення заощаджує місце для зберігання
- Передача документів: попередня обробка перед завантаженням на електронну пошту/хмару
- Пакетна обробка: автоматизоване стиснення за допомогою Celery
5.2 效果预估
| Тип документа | Типовий коефіцієнт стиснення | Примітки |
|---|---|---|
| Чисто текстовий документ | 10-25% | Найбільш помітний ефект |
| З великою кількістю зображень | 5-15% | Лише за рахунок оптимізації структури |
| Документи, що редагувалися кілька разів | 20-40% | Ефект збору сміття помітний |
| Скановані PDF | 0-5% | Вже у форматі зображення, обмежена оптимізація |
5.3 注意事项
- Резервне копіювання оригінального файлу: стиснення незворотне
- Перевірка цілісності вмісту: всебічна перевірка після стиснення
- Тестування якості друку: уникнення впливу на вихід
- Для масової обробки рекомендується використовувати розподілену архітектуру
六、同类方案对比
| Схема стиснення | Коефіцієнт стиснення | Втрата якості | Можливість пошуку тексту | Складність реалізації |
|---|---|---|---|---|
| Оптимізація структури PyMuPDF | 10-30% | Ні | Зберігається | Низька |
| Стиснення зниження якості зображень | 30-70% | Помітна | Зберігається | Середня |
| Перекодування PDF | 20-50% | Можлива втрата | Можлива втрата | Висока |
七、性能优化建议
- Пакетна обробка: використання багатопроцесорної обробки для одночасної обробки кількох файлів, підвищення ефективності
- Моніторинг прогресу: додавання функції зворотного виклику для моніторингу прогресу, покращення користувацького досвіду
- Інкрементальне стиснення: стиснення лише змінених сторінок у PDF, зменшення повторних операцій
- Кешування: зберігання вже стиснених файлів, щоб уникнути повторної обробки
八、总结
关键点回顾
- Це рішення базується на чотирьох ключових параметрах PyMuPDF:
garbage=4,deflate=True,clean=True,pretty=False, що дозволяє реалізувати безвтратне стиснення PDF; - Переваги рішення полягають у тому, що воно не втрачає якість документа, зберігає можливість пошуку тексту, є простим у реалізації та має хорошу сумісність;
- Ефект стиснення різних типів PDF може суттєво відрізнятися, оптимізація сканованих документів обмежена, а найкращі результати досягаються для чисто текстових документів, що редагувалися кілька разів.
Це рішення для безвтратного стиснення PDF поєднує практичність і безпеку, код простий для інтеграції, підходить для більшості сценаріїв обробки документів. Якщо вам потрібно досягти вищого коефіцієнта стиснення, ви також можете поєднати його з безвтратним стисненням зображень (наприклад, оптимізацією DPI), але слід звертати увагу на баланс між ефектом і складністю.
