3行Python代码快速实现对比两份PDF文档差异

 更新时间:2026年07月20日 08:39:43   作者:Eiceblue  
本文将教你用FreeSpire.PDF for Python免费库实现自动化文档差异检测,通过PdfComparer轻松生成高亮差异报告,支持纯文本对比和指定页面范围,有需要的小伙伴可以了解下

一、背景与需求

在文档版本管理、合同审核、技术文档迭代等实际工作中,快速准确地识别两个 PDF 文件之间的内容差异是一项常见而关键的需求。传统的人工逐页比对方式不仅耗时费力,而且在长文档场景下极易因视觉疲劳而遗漏细微改动。借助编程手段实现 PDF 自动化对比,既能大幅提升校对效率,又能保证结果的一致性与可追溯性。

本文基于 Free Spire.PDF for Python 国产免费库,系统介绍如何通过少量代码实现两个 PDF 文档的自动化差异检测,涵盖基础用法、高级配置以及实际应用中的注意事项。

二、环境准备

2.1 安装依赖

Free Spire.PDF for Python 支持通过 pip 一键安装,免费版本对单个 PDF 文件最多可处理 10 页内容,足以覆盖中小规模文档的对比需求。

pip install Spire.Pdf.Free

2.2 导入核心模块

在代码中需要引用两个关键命名空间,分别提供基础类型和 PDF 操作类:

from spire.pdf.common import *
from spire.pdf import *

三、核心对比机制

3.1 PdfComparer 类的工作原理

PdfComparer 是文档对比功能的核心类,其内部处理流程如下:

  • 接收两个 PdfDocument 对象,其中第一个作为基准文档(参照版本),第二个作为待比对文档(修订版本);
  • 逐页解析两个文档的文本内容和版面布局信息;
  • 基于内容相似度算法,智能识别出新增、删除和修改的文本片段;
  • 最终生成一份带有高亮标记的对比结果 PDF,直观展示所有差异。

3.2 差异类型的视觉标识

生成的对比报告通过不同颜色高亮区分差异类别:

  • 🔴 红色高亮:表示基准文档中存在、但待比对文档中已删除的内容;
  • 🟡 黄色高亮:表示待比对文档中新增、而基准文档中没有的内容;
  • 无高亮区域:表示两个文档对应位置的内容完全一致。

效果示意图如下:

四、基础实现:全文档对比

以下代码演示了如何实现两个 PDF 文档的完整对比,并输出可视化的差异报告。

from spire.pdf.common import *
from spire.pdf import *

def compare_pdf(base_path: str, revised_path: str, output_path: str) -> None:
    """
    对比两个 PDF 文档,生成带高亮标记的差异报告
    
    Args:
        base_path:  基准文档路径(作为参照版本)
        revised_path: 待比对文档路径(修订版本)
        output_path: 对比结果 PDF 的输出路径
    """
    # 加载两个 PDF 文档
    base_doc = PdfDocument(base_path)
    revised_doc = PdfDocument(revised_path)
    
    try:
        # 创建对比器,第一个参数为基准,第二个为待比较版本
        comparer = PdfComparer(base_doc, revised_doc)
        # 执行对比并保存结果
        comparer.Compare(output_path)
        print(f"对比完成,结果已保存至: {output_path}")
    finally:
        # 显式释放资源,避免内存泄漏
        base_doc.Dispose()
        revised_doc.Dispose()

# 使用示例
if __name__ == "__main__":
    compare_pdf("document1.pdf", "document2.pdf", "comparison_result.pdf")

关键说明

  • PdfComparer 构造函数的第一个参数决定了差异标注的参照基准,结果报告中的“删除”均指该版本中存在的内容;
  • 输出文件为标准 PDF 格式,可在任意 PDF 阅读器中打开并查看高亮标记。

五、高级对比配置

5.1 纯文本对比模式

默认情况下,对比算法会同时考察文本内容和排版布局(如字体、间距、图形等)的差异。如果业务场景仅关注文字内容的变更,而希望忽略格式调整带来的干扰,可以启用纯文本对比模式:

comparer = PdfComparer(base_doc, revised_doc)
# 开启仅文本对比,忽略排版和图形差异
comparer.PdfCompareOptions.OnlyCompareText
comparer.Compare(output_path)

该模式特别适用于合同条款的文字审核、技术文档的内容校验等场景,能够有效过滤因格式重排产生的无效差异标记。

5.2 指定页面范围对比

当文档页数较多时,往往只需关注特定章节或页面区间。通过 SetPageRanges 方法可精确限定对比范围,既提升效率,也避免无关页面的干扰:

comparer = PdfComparer(base_doc, revised_doc)
# 参数依次为:基准文档起始页、结束页,待比对文档起始页、结束页(索引均从 0 开始)
comparer.PdfCompareOptions.SetPageRanges(0, 2, 0, 2)
comparer.Compare(output_path)

上述示例仅对比两个文档的第 1 至第 3 页(含),在增量审核或定点校验场景中非常实用。

六、适用场景与限制

6.1 典型应用场景

  • 合同版本审核:快速定位合同条款的增删改,降低法务审核风险;
  • 技术文档迭代:清晰展示手册、规范等文档每次修订的具体变动;
  • 报表一致性检查:自动核对定期生成的数据报表,确保内容无误;
  • 自动化回归测试:作为文档生成系统的质量校验环节,比对输出是否符合预期。

6.2 功能限制说明

使用免费版时需了解以下限制:

  • 单个 PDF 文件最多处理 10 页,超出部分将被忽略;
  • 对比基于文本内容,对扫描件或纯图片 PDF(无可选文本层)无法有效识别;
  • 对极为复杂的排版(如多层嵌套表格、艺术字、矢量图形等),对比精度可能有所下降;
  • 结果输出为可视化 PDF 报告,暂不支持直接导出结构化的差异数据(如 JSON/XML)。

6.3 实践建议

  • 对比前请确认 PDF 为原生可选取文本的文档,而非图片型 PDF;
  • 若文档页数较多,建议结合 SetPageRanges 分批次处理,避免超出免费页数限制;
  • 每次对比完成后务必调用 Dispose() 释放文档对象,以优化内存占用;
  • 涉及敏感信息时,建议在本地环境离线运行,避免上传至第三方在线工具。

七、知识扩展

在 Python 中快速对比两份 PDF 文档的差异,主要取决于你关注的是文本内容的变化还是视觉布局的变化。下面分别提供两种实用的方法,附带可直接运行的代码。

方法一:文本内容对比(快速、轻量)

这种方法提取 PDF 的文本内容,然后使用 Python 内置的 difflib 生成差异报告。适合检测文字增删、修改,但忽略字体、图片、表格样式等视觉变化。

安装依赖

pip install PyPDF2

(或者使用 pdfplumber 以获得更好的文本提取效果)

pip install pdfplumber

代码示例(使用 pdfplumber

import pdfplumber
import difflib
import sys
def extract_text(pdf_path):
    """提取 PDF 所有页面的文本"""
    with pdfplumber.open(pdf_path) as pdf:
        text = ""
        for page in pdf.pages:
            text += page.extract_text() or ""
    return text
def compare_pdf_text(pdf1, pdf2, output_html="diff_report.html"):
    """对比两个 PDF 的文本差异,生成 HTML 报告"""
    text1 = extract_text(pdf1)
    text2 = extract_text(pdf2)
    # 按行分割
    lines1 = text1.splitlines()
    lines2 = text2.splitlines()
    # 生成差异 HTML
    diff = difflib.HtmlDiff(wrapcolumn=80)
    html = diff.make_file(lines1, lines2, fromdesc=pdf1, todesc=pdf2)
    with open(output_html, "w", encoding="utf-8") as f:
        f.write(html)
    print(f"差异报告已生成:{output_html}")
    # 也可简单打印差异摘要
    differ = difflib.Differ()
    diff_lines = list(differ.compare(lines1, lines2))
    added = sum(1 for line in diff_lines if line.startswith('+ '))
    removed = sum(1 for line in diff_lines if line.startswith('- '))
    print(f"新增行数:{added},删除行数:{removed}")
if __name__ == "__main__":
    compare_pdf_text("old.pdf", "new.pdf")
  • 优点:速度快,无需额外图像处理库,输出易于阅读的 HTML 报告。
  • 缺点:无法检测图片、表格位置、颜色、字体等非文本变化。

方法二:视觉对比(更全面,适用于版式差异)

通过将 PDF 的每一页转换为图像,然后计算像素差异,可以检测到任何视觉上的改变(文字、图片、布局、颜色等)。适合用于需要精确对比版式的场景。

安装依赖

pip install pdf2image pillow numpy opencv-python

此外,pdf2image 依赖 poppler,需要提前安装:

  • Ubuntu/Debiansudo apt-get install poppler-utils
  • macOSbrew install poppler
  • Windows:下载 poppler 并设置 bin 目录到环境变量

代码示例(使用 OpenCV)

import cv2
import numpy as np
from pdf2image import convert_from_path
from PIL import Image, ImageChops
def compare_pdf_images(pdf1, pdf2, output_diff="diff_image.png"):
    """
    逐页对比两个 PDF 的图像,输出第一处差异的标注图像
    """
    # 转换为图像列表(分辨率可调)
    images1 = convert_from_path(pdf1, dpi=150)
    images2 = convert_from_path(pdf2, dpi=150)
    # 确保页数相同
    if len(images1) != len(images2):
        print(f"页数不同:{len(images1)} vs {len(images2)},无法逐页对比")
        return
    for i, (img1, img2) in enumerate(zip(images1, images2)):
        # 转换为 numpy 数组(OpenCV 格式)
        np_img1 = np.array(img1)
        np_img2 = np.array(img2)
        # 计算像素差异
        diff = cv2.absdiff(np_img1, np_img2)
        diff_gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
        _, thresh = cv2.threshold(diff_gray, 30, 255, cv2.THRESH_BINARY)
        # 如果有差异,标记并保存
        if np.sum(thresh) > 0:
            # 在差异区域画框
            contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            for cnt in contours:
                x, y, w, h = cv2.boundingRect(cnt)
                cv2.rectangle(np_img1, (x, y), (x+w, y+h), (0, 0, 255), 2)
            # 保存标注后的图像
            result_img = Image.fromarray(np_img1)
            result_img.save(f"diff_page_{i+1}.png")
            print(f"第 {i+1} 页存在差异,已保存标注图像 diff_page_{i+1}.png")
            break
    else:
        print("所有页面完全相同")
if __name__ == "__main__":
    compare_pdf_images("old.pdf", "new.pdf")

优点:能捕捉所有视觉变化,包括文字、图片、颜色、边框等。

缺点:速度较慢,依赖外部工具和库,无法直接指出修改了哪些文本。

方法三:专业命令行工具(推荐临时使用)

如果不想写代码,可以使用命令行工具 pdf-diff(基于 Node.js,但可在 Python 中调用)或 comparepdf(Linux 工具)。示例:

# 安装 comparepdf(Ubuntu)
sudo apt-get install comparepdf
comparepdf --diff=diff.pdf old.pdf new.pdf

这会生成一个带高亮的差异 PDF。

八、总结

通过 PdfComparer 类,开发者仅需少量代码即可实现 PDF 文档的自动化差异检测。灵活运用纯文本对比模式和页面范围设定,可适配合同审核、版本校验、回归测试等多种业务场景。对于中小规模的文档对比需求,Free Spire.PDF for Python 免费版的功能范围已能覆盖绝大多数日常使用场景,是一种轻量且高效的解决方案。

到此这篇关于3行Python代码快速实现对比两份PDF文档差异的文章就介绍到这了,更多相关Python对比PDF文档内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Elasticsearches的集群搭建及数据分片过程详解

    Elasticsearches的集群搭建及数据分片过程详解

    这篇文章主要为大家介绍了Elasticsearches的集群搭建及数据分片过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • python3.8动态人脸识别的实现示例

    python3.8动态人脸识别的实现示例

    这篇文章主要介绍了python3.8动态人脸识别的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Python使用matplotlib创建Gif动图的思路

    Python使用matplotlib创建Gif动图的思路

    这篇文章主要介绍了Python使用matplotlib创建Gif动图,我们将讨论matplotlib提供的名为“Animation”的动画库之一,Python二维绘图库是Matplolib可以轻松创建绘图、直方图、条形图、散点图等,需要的朋友可以参考下
    2022-04-04
  • pytorch建立mobilenetV3-ssd网络并进行训练与预测方式

    pytorch建立mobilenetV3-ssd网络并进行训练与预测方式

    这篇文章主要介绍了pytorch建立mobilenetV3-ssd网络并进行训练与预测方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Python内存池机制的实现

    Python内存池机制的实现

    Python内存池是Python解释器为了提高内存分配效率而设计的一种内存管理机制,本文主要介绍了Python内存池机制的实现,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04
  • Python数值求解微分方程方法(欧拉法,隐式欧拉)

    Python数值求解微分方程方法(欧拉法,隐式欧拉)

    这篇文章主要介绍了Python数值求解微分方程方法(欧拉法,隐式欧拉),文章围绕主题展开详细的内介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Python绘制3D立体花朵示例详解

    Python绘制3D立体花朵示例详解

    情人节送玫瑰花千篇一律?本文将为大家介绍利用Python绘制多种3D立体花朵的示例代码,让女友感受一下程序员的浪漫!快来跟随小编一起学习一下吧
    2021-12-12
  • python将unicode和str互相转化的实现

    python将unicode和str互相转化的实现

    这篇文章主要介绍了python将unicode和str互相转化的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • 通过Django Admin+HttpRunner1.5.6实现简易接口测试平台

    通过Django Admin+HttpRunner1.5.6实现简易接口测试平台

    这篇文章主要介绍了通过Django Admin+HttpRunner1.5.6实现简易接口测试平台,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Python中使用urllib2防止302跳转的代码例子

    Python中使用urllib2防止302跳转的代码例子

    这篇文章主要介绍了Python中使用urllib2防止302跳转的代码例子,即避免302跳转的实现,需要的朋友可以参考下
    2014-07-07

最新评论