Разделить PDF на документы с несколькими страницами каждый.

Вопрос или проблема

Существует множество ресурсов в интернете, объясняющих, как можно разделить PDF-файл на множество файлов, по одной странице в каждом.

Но как можно разбить их на части по, скажем, пять страниц каждая? Я изучил стандартные инструменты такие как pdftk, но не нашел подходящей опции.

pdftk может эффективно извлекать фиксированный набор страниц. С небольшим дополнительным скриптингом, это делает то, что мне нужно:

number=$(pdfinfo -- "$file" 2> /dev/null | awk '$1 == "Pages:" {print $2}')
count=$((number / pagesper))
filename=${file%.pdf}

counter=0
while [ "$count" -gt "$counter" ]; do 
  start=$((counter*pagesper + 1));
  end=$((start + pagesper - 1));

  counterstring=$(printf %04d "$counter")
  pdftk "$file" cat "${start}-${end}" output "${filename}_${counterstring}.pdf"

  counter=$((counter + 1))
done

Это предполагает, что у вас есть количество страниц в каждом отрезке в $pagesper и имя исходного PDF-файла в $file.

Если у вас установлен acroread, вы также можете использовать

acroread -size a4 -start "$start" -end "$end" -pairs "$file" "${filename}_${counterstring}.ps"

acroread также предлагает опцию -toPostScript, которая может быть полезной.

Также смотрите pdfseparate и pdfunite из poppler-utils. pdfseparate разбивает файл на файлы по одной странице, что упрощает их последующую сборку вручную или (полу)автоматически с помощью pdfunite.

Как, например, с помощью zsh:

autoload zargs

reunite() pdfunite "$@" file-$1-$argv[-1].pdf

pdfseparate file.pdf p%d
zargs -n 5 p<->(n) -- reunite
rm -f p<->

разделит file.pdf на file-p1-p5.pdf, file-p6-p10.pdf

Я нахожу Python с библиотекой PyPdf удобным для задач, которые pdftk не выполняет удобно (или вообще).

PyPDF претерпел несовместимые изменения за эти годы. Вот версия, которая работает с Python 3 и PyPDF2 2.12. Возможно, потребуется корректировка для других версий.

#!/usr/bin/env python3
import sys
from PyPDF2 import PdfFileWriter, PdfFileReader

# Разбор командной строки
if len(sys.argv) < 2 or sys.argv[1][-4:] != '.pdf':
    sys.stderr.write('Использование: ' + sys.argv[0] + ''' FILE.pdf N
Разделите FILE.pdf на части по N страниц каждая.
''')
    exit(3)
pages_per_file = int(sys.argv[2])

base_name = sys.argv[1][:-4] + '-'
input_pdf = PdfFileReader(open(sys.argv[1], 'rb'))
output_pdf = PdfFileWriter()
num_pages = input_pdf.getNumPages()
for i in range(num_pages):
    output_pdf.addPage(input_pdf.getPage(i))
    if (i + 1) % pages_per_file == 0 or i + 1 == num_pages:
        output_file = open(base_name + str(i // pages_per_file + 1) + '.pdf', "wb")
        output_pdf.write(output_file)
        output_file.close()
        output_pdf = PdfFileWriter()

Решение, предложенное Рафаэлем, имеет недостаток: если у вас нечетное количество страниц, последние просто игнорируются. Вот улучшенное решение, которое работает также с нечетным количеством страниц.
Опять же, предполагается, что у вас есть количество страниц в каждом отрезке в $pagesper и имя исходного PDF-файла в $file.

number=$(pdfinfo -- "$file" 2> /dev/null | awk '$1 == "Pages:" {print $2}')

count=$((($number+$pagesper-1)/$pagesper))
filename=${file%.pdf}

counter=0
while [ "$count" -gt "$counter" ]; do
  start=$((counter*pagesper + 1));
  end=$((start + pagesper - 1));
  if [ $end -gt $number ]; then
    end=$number
  fi

  counterstring=$(printf %04d "$counter")
  pdftk "$file" cat "${start}-${end}" output "${filename}_${counterstring}.pdf"
  counter=$((counter + 1))
done

Ответ или решение

Разделение PDF-документов на файлы с определенным количеством страниц представляет собой задачу, с которой могут столкнуться специалисты в области информационных технологий и административные работники. Часто требуется сжать содержимое большого документа, создавая множество меньших файлов для удобства обращения или передачи. В данной справке мы обсудим несколько способов добиться этого.

Теоретические основы

PDF-файлы — это универсальный формат электронных документов, известный своей возможностью сохранять исходное форматирование независимо от устройства или программы просмотра. Однако из-за этой универсальности возникают некоторые сложности при необходимости автоматического разделения документа на части. Основные инструменты работы с PDF, такие как pdftk, предлагают базовую функциональность, но не все они поддерживают разделение на файлы с фиксированным числом страниц.

Подход с использованием командной строки и pdftk

Первый подход к решению задачи заключается в использовании командной строки и pdftk. Этот инструмент позволяет извлекать конкретные страницы из большого документа в новый файл. Однако для решения задачи разделения на файлы с несколькими страницами потребуется дополнительная скриптовая логика:

  1. Получение общее количество страниц: Используйте pdfinfo для извлечения информации о документе, в частности, количеству страниц.

    number=$(pdfinfo -- "$file" 2> /dev/null | awk '$1 == "Pages:" {print $2}')
  2. Настройка скрипта для циклического создания новых документов: Определяется количество файлов, необходимых для полного разделения PDF, и настраивается цикл, который будет обрабатывать каждую группу страниц по отдельности.

    while [ "$count" -gt "$counter" ]; do 
      start=$((counter*pagesper + 1));
      end=$((start + pagesper - 1));
      if [ $end -gt $number ]; then
        end=$number
      fi
    
      counterstring=$(printf %04d "$counter")
      pdftk "$file" cat "${start}-${end}" output "${filename}_${counterstring}.pdf"
    
      counter=$((counter + 1))
    done

Этот метод требует установленных утилит из пакета poppler-utils, включая pdfinfo и pdftk.

Использование Python и библиотеки PyPDF2

Альтернативным решением является использование Python с библиотекой PyPDF2. Этот подход дает значительное преимущество в возможностях автоматизации и интеграции в более сложные рабочие процессы.

  1. Чтение документа: Сначала открываем оригинальный файл для чтения.

    input_pdf = PdfFileReader(open(sys.argv[1], 'rb'))
  2. Итерация по страницам и запись в новые файлы: Определяем логики обработки каждой страницы и создания новых файлов на основе указанного количества страниц на файл.

    for i in range(num_pages):
        output_pdf.addPage(input_pdf.getPage(i))
        if (i + 1) % pages_per_file == 0 or i + 1 == num_pages:
            output_file = open(base_name + str(i // pages_per_file + 1) + '.pdf', "wb")
            output_pdf.write(output_file)
            output_file.close()
            output_pdf = PdfFileWriter()

Этот метод является более современным и позволяет легко масштабировать скрипт или интегрировать его в более сложные системы управления документами.

Применение на практике

Выбор наиболее подходящего способа будет зависеть от ваших задач. Если разовая задача требует быстрого решения, подход с использованием pdftk может быть достаточным. Если же требуется более автоматизированное решение или интеграция в пайплайн обработки данных, то предпочтительнее использовать Python.

Итак, у вас есть несколько методов и сценариев для разделения PDF-документов на части по числу страниц. Выбор подхода будет существенно зависеть от ваших специфических требований и окружения. Завершая, напомним, что владение различными инструментами и знаниями — ключ к успешной и эффективной работе с PDF-документами.

Оцените материал
Добавить комментарий

Капча загружается...