Как проще и быстрее разбить pdf на часть размером до 5Мб
У меня есть задача копировать файлы 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:
print(from_page, to_page)
new_pdf = fitz.open()
new_pdf.insert_pdf(source_pdf, from_page=from_page, to_page=to_page)
new_pdf.save("./tmp.pdf")
pdf_size_mb = get_file_size_in_mb("./tmp.pdf")
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
new_pdf.close()
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
Как еще можно реализовать такой алгоритм чтобы ускорить процесс?
Ответы (1 шт):
Автор решения: Kadenza
→ Ссылка
Придумал быстрое решение. Но буду благодарен за подсказки
# получить размер файла в Мб
def get_file_size_in_mb(file_path):
size_in_bytes = os.path.getsize(file_path)
size_in_mb = size_in_bytes / (1024 * 1024)
return size_in_mb
# Получить диапазоны страниц для частей файла размером до max_size_mb
def get_range_page_by_size(pdf_obj, max_size_mb, tmp_path=tmp_path_for_files):
sizes_for_page = []
count_pages = pdf_obj.page_count
tmp_path = os.path.join(tmp_path, 'tmp.pdf')
try:
for page in range(count_pages):
new_pdf = fitz.open()
new_pdf.insert_pdf(pdf_obj, from_page=page, to_page=page)
new_pdf.save(tmp_path)
page_size = get_file_size_in_mb(tmp_path)
os.remove(tmp_path)
# если размер одной страницы превышает максимальный размер файла
if page_size > max_size_mb:
return []
sizes_for_page.append(page_size)
ranges = []
current_range = []
current_size = 0
for i, size in enumerate(sizes_for_page):
if current_size + size <= max_size_mb:
current_range.append(i)
current_size += size
else:
ranges.append([current_range[0], current_range[-1]])
current_range = [i]
current_size = size
if len(current_range) > 0:
ranges.append([current_range[0], current_range[-1]])
return ranges
except Exception as e:
print(e)
return []
# Переместить и разбить при необходимости 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)
range_page_by_size = get_range_page_by_size(source_pdf, max_size_mb=max_pdf_size_mb)
if len(range_page_by_size) == 0:
report_message = f"Ошибка: не удалось разбить pdf файл {source_pdf_path} на части меньше {max_pdf_size_mb} МБ"
else:
post_index = 1
if not os.path.exists(output_dir):
os.mkdir(output_dir)
for from_page, to_page in range_page_by_size:
new_pdf = fitz.open()
new_pdf.insert_pdf(source_pdf, from_page=from_page, to_page=to_page)
new_pdf_save_name = f"{new_pdf_name}_{post_index}.pdf"
save_path = os.path.join(output_dir, new_pdf_save_name)
new_pdf.save(save_path)
new_pdf.close()
result_paths_pdf.append(save_path)
post_index += 1
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