Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Как проще и быстрее разбить pdf на часть размером до 5Мб

иля Гуру (4455), на голосовании 2 недели назад
У меня есть задача копировать файлы pdf из одной папки в другую. Если какие-то файлы pdf более 5Мб то их надо разбить на части до 5Мб.

Я написал функцию, которая с этим справляется (просьба строго не судить) Но проблема в том что эта функция работает оооочень долго для pdf у которых более 100 страниц. А мне требуется обработать сотни тысяч документов

Как еще можно реализовать такой алгоритм чтобы ускорить процесс?


 # Переместить и разбить при необходимости pdf 
def copy_and_split_pdf(source_pdf_path, output_dir, new_pdf_name, max_pdf_size_mb=5.0):
report_message = ""
result_paths_pdf = []

try:
file_size_in_mb = get_file_size_in_mb(source_pdf_path)
if file_size_in_mb > max_pdf_size_mb:
source_pdf = fitz.open(source_pdf_path)

result_pdfs_obj = []
qty_pages = source_pdf.page_count
from_page = 0
to_page = qty_pages-1

while True:
new_pdf = fitz.open()
pdf_stream = io.BytesIO()
new_pdf.insert_pdf(source_pdf, from_page=from_page, to_page=to_page)
new_pdf.save(pdf_stream)
pdf_size_bytes = pdf_stream.getbuffer().nbytes
pdf_size_mb = pdf_size_bytes / (1024 * 1024)
pdf_stream.close()

if pdf_size_mb < max_pdf_size_mb:
result_pdfs_obj.append(new_pdf)

# print(from_page, to_page, pdf_size_mb)
if to_page == qty_pages - 1:
break
from_page = to_page+1
to_page = qty_pages-1
else:
if from_page == to_page:
for pdf in result_pdfs_obj:
pdf.close()
result_pdfs_obj = []
break
to_page -= 1

source_pdf.close()

if len(result_pdfs_obj) == 0:
report_message = f"Ошибка: не удалось разбить pdf файл {source_pdf_path} на части меньше {max_pdf_size_mb} МБ"
else:

if not os.path.exists(output_dir):
os.mkdir(output_dir)

for pdf in result_pdfs_obj:
new_pdf_save_name = f"{new_pdf_name}_{result_pdfs_obj.index(pdf)+1}.pdf"
save_path = os.path.join(output_dir, new_pdf_save_name)
pdf.save(save_path)
pdf.close()
result_paths_pdf.append(save_path)
else:

if not os.path.exists(output_dir):
os.mkdir(output_dir)

new_pdf_name = f"{new_pdf_name}.pdf"
save_path = os.path.join(output_dir, new_pdf_name)
shutil.copy2(source_pdf_path, save_path)
result_paths_pdf.append(save_path)

except Exception as e:
print(e)
report_message = f"Ошибка: {e} (Не удалось загрузить файл: {source_pdf_path})"
finally:
return report_message, result_paths_pdf
Голосование за лучший ответ
V̲i̲s̲t̲a̲s̲t̲e̲r̲ Искусственный Интеллект (265313) 1 месяц назад
хм.. ты даже не пытаешься использовать процессорный пул и... много операций сброса на диск.. Ладно.

Можно так:
— Фильтруешь крупное файло и с помощью пакетной функции в Wondershare PDFelement сжимаешь в другую папку (обычно получается двухкратное сжатие легко)
— Сжатую папку снова фильтруешь на остатки и списком загружаешь в PDF Shaper Ultimate(есть ком. строка) и делишь на мелкие части, к примеру по 100 стр.

Остается склепать автоматизацию этих приложений. Но они работают в разы быстрее Python, несмотря на то, что ты применяешь pdf-библу.

ну и говнокод тоже надо допилить..хотя это может уже и не потребоваться после первого этапа сжатия.. Хотя я бы всю эту бороду переписал на C++, это для него задача
Похожие вопросы