如何使用Python获取两个PDF文件的差异?
如何使用Python获取两个PDF文件的差异?
虽然这个问题已经很久了,但我想我可以为这个问题做出贡献。我们有几个应用程序生成大量的PDF文件。其中一个应用程序是用Python编写的,最近我想编写集成测试来检查PDF生成是否正常工作。
测试PDF生成很困难,因为PDF文件的规格非常复杂和非确定性。由相同输入数据生成的两个PDF文件会生成不同的文件,所以直接文件比较是不可行的。
解决方案:我们必须测试它们的外观(因为这是确定性的!)。
在我们的情况下,PDF是使用reportlab软件包生成的,但从测试的角度来看,这并不重要,我们只需要一个文件名或来自生成器的PDF 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`是生成的PDF的字节流 # 如果使用reportlab,在完成所有绘制后,可以通过在Canvas实例上调用`getpdfdata()`来获得它 pdf = PdfGenerator().generate() # PDF是矢量的,所以在转换为图像时需要设置分辨率 actual_img = Image(blob=pdf, resolution=150) filename = os.path.join(DIR, 'expected.pdf') # 确保使用与上面相同的分辨率 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]`使用`root_mean_square`度量从0到1变化,我们在这里接受了与示例期望文件的所有通道上的差异高达1%。
如何使用Python获取两个PDF文件的差异?
在脚本生成PDF文件的回归测试中,我不知道您的使用情况,但我通过以下步骤来比较PDF文件的差异:
1. 使用Ghostscript将每个页面转换为图像
2. 使用PIL库将每个页面与标准PDF文件的页面图像进行比较
以下是示例代码:
im1 = Image.open(imagePath1) im2 = Image.open(imagePath2) imDiff = ImageChops.difference(im1, im2)
在我这个用例中,这种方法可以标记由于代码更改而引入的任何更改。
关于您的第一步骤,是否有一些参考资料可以提供?
解决方法:
1. 安装Ghostscript和PIL库。
2. 使用Ghostscript将PDF文件的每个页面转换为图像。
3. 使用PIL库比较每个页面的图像与标准PDF文件的页面图像。
4. 标记任何差异或更改。
希望这可以帮助您解决问题!
如何使用Python获取两个PDF文件的差异?
在这个问题中,“差异”是指PDF文件中的文本差异还是一些布局变化(例如,嵌入的图形被调整大小)。第一个很容易检测到,而第二个几乎不可能获取(PDF是一个非常复杂的文件格式,提供了无尽的文件格式化能力)。
如果您想获取文本差异,只需在两个PDF上运行一个PDF转文本工具,然后使用Python的内置diff库获取转换后的文本的差异。
这个问题涉及到在Python中进行PDF到文本转换的问题:Python模块用于将PDF转换为文本。
这种方法的可靠性取决于您使用的PDF生成器。如果您使用Adobe Acrobat和一些基于Ghostscript的PDF创建器从相同的Word文档生成两个PDF,即使源文档相同,您可能仍然会得到一个差异。
这是因为有数十种方法可以将源文档的信息编码为PDF,并且每个转换器都使用不同的方法。通常,PDF转文本转换器无法确定正确的文本流,特别是在复杂的布局或表格中。
只需要文本即可,PDF生成器不应该是个问题。
如果您确实需要支持图像,您可以从PDF中提取JPG图像,或者将PDF转换为图像并进行比较。