如何在python中获取两个PDF文件的差异?

Gou*_*ham 7 python pdf

我需要找到两个pdf文件之间的区别.有没有任何python相关工具有一个功能直接给出2 PDF的差异?

Vic*_*der 8

尽管这个问题已经很老了,但我的猜测是我可以为这个主题做出贡献。

我们有多个应用程序生成大量 PDF。其中一个应用程序是用 Python 编写的,最近我想编写集成测试来检查 PDF 生成是否正常工作。

测试 PDF 生成非常困难,因为 PDF 文件的规格非常复杂且不确定。使用完全相同的输入数据生成的两个 PDF 将生成不同的文件,因此放弃直接文件比较。

解决方案:我们必须测试它们的外观(因为应该是确定性的!)。

在我们的例子中,PDF 是通过reportlab包生成的,但这从测试的角度来看并不重要,我们只需要生成器中的文件名或 PDF blob(字节)。我们还需要一个包含“良好”PDF 的期望文件,以便与来自生成器的 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)
Run Code Online (Sandbox Code Playgroud)

0.01值是我们可以容忍的小差异的最低值。考虑到diff[1]使用指标的变化范围为 0 到 1 root_mean_square,与样本预期文件相比,我们在此接受所有通道上最多 1% 的差异。


fbu*_*ger 6

"差异"是什么意思?PDF文本或某些布局更改的差异(例如,调整了嵌入图形的大小).第一个很容易检测,第二个几乎不可能得到(PDF是一种非常复杂的文件格式,提供无限的文件格式化功能).

如果你想获得文本差异,只需在两个PDF上运行pdf to text实用程序,然后使用Python的内置差异库来获得转换文本的差异.

这个问题涉及python中的pdf到文本转换:用于将PDF转换为文本的Python模块.

此方法的可靠性取决于您使用的PDF生成器.如果您使用例如Adobe Acrobat和一些基于Ghostscript的PDF-Creator从SAME word文档制作两个PDF,尽管源文档是相同的,您仍可能会得到差异.

这是因为有许多方法可以将源文档的信息编码为PDF,并且每个转换器使用不同的方法.通常,pdf到文本转换器无法找出正确的文本流,尤其是对于复杂的布局或表格.


Anu*_*yal 5

我不知道你的用例,但是对于使用 reportlab 生成 pdf 的脚本的回归测试,我做 diff pdfs

  1. 使用 ghostsript 将每个页面转换为图像
  2. 使用 PIL 将每个页面与标准 pdf 的页面图像进行比较

例如

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

imDiff = ImageChops.difference(im1, im2)
Run Code Online (Sandbox Code Playgroud)

在我的情况下,这适用于标记由于代码更改而引入的任何更改。