Как получить разницу двух файлов PDF в Python? - PullRequest
6 голосов
/ 21 августа 2009

Мне нужно найти разницу между двумя файлами PDF. Есть ли в каком-либо инструменте, связанном с Python, функция, которая напрямую отображает разницу между двумя PDF-файлами?

Ответы [ 5 ]

5 голосов
/ 21 августа 2009

Что вы подразумеваете под "разницей"? Разница в тексте PDF или некоторые изменения макета (например, размер встроенного рисунка был изменен). Первый легко обнаружить, второй почти невозможно получить (PDF - ОЧЕНЬ сложный формат файла, который предлагает бесконечные возможности форматирования файла).

Если вы хотите получить разность текста, просто запустите утилиту pdf to text для двух файлов PDF, а затем используйте встроенную библиотеку различий Python, чтобы получить разницу между преобразованными текстами.

Этот вопрос касается преобразования pdf в текст в python: Модуль Python для преобразования PDF в текст .

Надежность этого метода зависит от используемых вами генераторов PDF. Если вы используете, например, Adobe Acrobat и некоторые PDF-Creator на основе Ghostscript для создания двух PDF-файлов из одного и того же документа Word, вы все равно можете получить разницу, хотя исходный документ идентичен.

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

3 голосов
/ 21 августа 2009

Я не знаю ваш вариант использования, но для регрессионных тестов скрипта, который генерирует pdf с использованием reportlab, я делаю diff pdfs на

  1. Преобразование каждой страницы в изображение с помощью ghostsript
  2. Отклонение каждой страницы от изображения страницы стандартного PDF с использованием PIL

1009 * например *

im1 = Image.open(imagePath1)
im2 = Image.open(imagePath2)

imDiff = ImageChops.difference(im1, im2)

В моем случае это работает для отметки любых изменений, внесенных из-за изменений кода.

2 голосов
/ 11 февраля 2014

Встретил тот же вопрос на моем зашифрованном pdf unittest, ни pdfminer, ни pyPdf для меня не работают.

Вот две команды (pdftocairo, pdftotext), которые отлично работают в моем тесте. (Ubuntu Install: apt-get install poppler-utils)

Вы можете получить pdf контент по:

from subprocess import Popen, PIPE

def get_formatted_content(pdf_content):
    cmd = 'pdftocairo -pdf - -' # you can replace "pdftocairo -pdf" with "pdftotext" if you want to get diff info
    ps = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    stdout, stderr = ps.communicate(input=pdf_content)
    if ps.returncode != 0:
        raise OSError(ps.returncode, cmd, stderr)
    return stdout

Кажется, pdftocairo может перерисовывать файлы pdf, pdftotext может извлекать весь текст.

И тогда вы можете сравнить два файла PDF:

c1 = get_formatted_content(open('f1.pdf').read())
c2 = get_formatted_content(open('f2.pdf').read())
print(cmp(c1, c2)) # for binary compare
# import difflib
# print(list(difflib.unified_diff(c1, c2))) # for text compare
0 голосов
/ 28 февраля 2019

Несмотря на то, что этот вопрос довольно старый, я думаю, что могу внести свой вклад в тему.

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

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

Решение: нам нужно проверить, как они выглядят (потому что ТО должно быть детерминированным!).

В нашем случае PDF-файлы создаются с помощью пакета reportlab, но это не имеет значения с точки зрения теста, нам просто нужно имя файла или BLOB-объект (байты) из генератора. Нам также нужен файл ожидания, содержащий «хороший» PDF-файл для сравнения с файлом, полученным из генератора.

PDF-файлы преобразуются в изображения и затем сравниваются. Это можно сделать несколькими способами, но мы решили использовать ImageMagick, потому что он чрезвычайно универсален и очень зрел, с привязками практически для любого языка программирования. Для Python 3 привязки предлагаются пакетом Wand.

Тест выглядит примерно так: Конкретные детали нашей реализации были удалены, а пример был упрощен:

import os
from unittest import TestCase
from wand.image import Image
from app.generators.pdf import PdfGenerator


DIR = os.path.dirname(__file__)


class PdfGeneratorTest(TestCase):

    def test_generated_pdf_should_match_expectation(self):
        # `pdf` is the blob of the generated PDF
        # If using reportlab, this is what you get calling `getpdfdata()`
        # on a Canvas instance, after all the drawing is complete
        pdf = PdfGenerator().generate()

        # PDFs are vectorial, so we need to set a resolution when
        # converting to an image
        actual_img = Image(blob=pdf, resolution=150)

        filename = os.path.join(DIR, 'expected.pdf')

        # Make sure to use the same resolution as above
        with Image(filename=filename, resolution=150) as expected:
            diff = actual.compare(expected, metric='root_mean_square')
            self.assertLess(diff[1], 0.01)

0.01 настолько низок, насколько мы можем терпеть небольшие различия. Учитывая, что diff[1] изменяется от 0 до 1 с использованием метрики root_mean_square, мы принимаем здесь разницу до 1% по всем каналам по сравнению с образцом ожидаемого файла.

0 голосов
/ 21 августа 2009

Проверьте это, это может быть полезно: http://pybrary.net/pyPdf/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...