Python 实现 PDF 注释(高亮、批注与图章)

0 阅读7分钟

使用 Python 为 PDF 文档添加注释和标注

在 PDF 文档处理场景中,添加注释是一项实用且常见的需求。无论是文档审阅、协作编辑还是内容标记,注释功能都能帮助我们在不修改原文的情况下添加说明、高亮重点或插入批注。本文将详细介绍如何使用 Python 在 PDF 文档中添加各种类型的注释和标注。

为什么需要为 PDF 添加注释

手动在 PDF 中添加注释不仅效率低下,而且难以保持一致的格式。通过编程方式实现这一功能具有以下优势:

  • 批量处理 - 一次性为多个文档添加相同格式的注释
  • 精确控制 - 像素级定位注释位置,确保与文档内容完美对应
  • 类型丰富 - 程序化创建高亮、下划线、自由文本、图章等多种注释
  • 样式一致性 - 统一设置颜色、透明度、边框等属性,保持专业外观

环境准备

首先需要安装支持 PDF 操作的 Python 库。本文使用 Spire.PDF for Python,它提供了完整的 PDF 注释 API。

pip install Spire.PDF

该库支持多种注释类型,包括文本标记、自由文本、图章、线条、附件等,能够满足各种文档标注需求。

核心注释类型

Spire.PDF 支持丰富的注释类型,每种类型都有其特定的应用场景:

1. 自由文本注释(Free Text Annotation)

自由文本注释允许在 PDF 页面上添加可编辑的文本框,适用于添加详细说明或批注。

from spire.pdf import *

# 创建 PDF 文档
doc = PdfDocument()
page = doc.Pages.Add()

# 定义注释区域
rect = RectangleF(100.0, 200.0, 200.0, 50.0)

# 创建自由文本注释
textAnnotation = PdfFreeTextAnnotation(rect)
textAnnotation.Text = "\n这是一条自由文本注释"

# 设置字体和边框
font = PdfTrueTypeFont("微软雅黑", 12.0, PdfFontStyle.Regular, True)
textAnnotation.Font = font

# 设置边框样式
border = PdfAnnotationBorder(1.5)
textAnnotation.Border = border
textAnnotation.BorderColor = PdfRGBColor(Color.get_Blue())

# 设置线条末端样式
textAnnotation.LineEndingStyle = PdfLineEndingStyle.Circle

# 设置背景颜色和透明度
textAnnotation.Color = PdfRGBColor(Color.get_LightBlue())
textAnnotation.Opacity = 0.8

# 添加到页面
page.AnnotationsWidget.Add(textAnnotation)

# 保存文档
doc.SaveToFile("FreeTextAnnotation.pdf")
doc.Close()

关键 API 说明:

  • PdfFreeTextAnnotation - 创建可编辑文本注释,需要指定矩形区域
  • PdfAnnotationBorder - 定义边框宽度,使注释外观更加清晰
  • PdfLineEndingStyle - 控制注释边框的末端样式(圆形、箭头、方形等)
  • Opacity - 设置透明度(0.0-1.0),0.0 完全透明,1.0 完全不透明

2. 文本标记注释(Text Markup Annotation)

文本标记注释用于高亮、下划线或删除线标记特定文本,是文档审阅中最常用的功能。

from spire.pdf import *

# 加载现有 PDF 文档
doc = PdfDocument()
doc.LoadFromFile("template.pdf")
page = doc.Pages[0]

# 获取要标记的文本位置
font = PdfTrueTypeFont("微软雅黑", 12.0, PdfFontStyle.Regular, True)
format = PdfStringFormat()

# 绘制提示文本
prompt = "需要高亮的文本:"
page.Canvas.DrawString(prompt, font, PdfBrushes.get_DodgerBlue(), 0.0, 50.0)

# 计算目标文本位置
x = font.MeasureString(prompt, format).Width
label = "这是一个重要段落"
page.Canvas.DrawString(label, font, PdfBrushes.get_OrangeRed(), x, 50.0)

# 创建高亮注释
incorrectWordLocation = PointF(x, 50.0)
markupText = "重要内容提醒"
annotation = PdfTextMarkupAnnotation(
    markupText, 
    "重要段落",
    RectangleF(x, 50.0, 100.0, 20.0), 
    font
)

# 设置高亮类型为高亮显示
annotation.TextMarkupAnnotationType = PdfTextMarkupAnnotationType.Highlight

# 设置高亮颜色
annotation.TextMarkupColor = PdfRGBColor(Color.get_Yellow())

# 添加到页面
page.AnnotationsWidget.Add(annotation)

# 保存文档
doc.SaveToFile("TextMarkupAnnotation.pdf")
doc.Close()

支持的标记类型:

  • Highlight - 高亮显示,类似荧光笔效果
  • Underline - 添加下划线
  • StrikeOut - 添加删除线
  • Squiggly - 添加波浪线

3. 线条注释(Line Annotation)

线条注释用于在文档中绘制带箭头的直线,适用于指示、连接或测量。

from spire.pdf import *

doc = PdfDocument()
page = doc.Pages.Add()

# 定义线条的起点和终点坐标 [x1, y1, x2, y2]
linePoints = [100, 400, 300, 400]

# 创建线条注释
lineAnnotation = PdfLineAnnotation(linePoints, "尺寸标注")

# 设置线条意图(影响阅读器的显示方式)
lineAnnotation.LineIntent = PdfLineIntent.LineDimension

# 设置起点和终点的样式
lineAnnotation.BeginLineStyle = PdfLineEndingStyle.ClosedArrow
lineAnnotation.EndLineStyle = PdfLineEndingStyle.Diamond

# 设置线条颜色和背景色
lineAnnotation.InnerLineColor = PdfRGBColor(Color.get_Green())
lineAnnotation.BackColor = PdfRGBColor(Color.get_Green())

# 设置边框样式
lineAnnotation.lineBorder.BorderStyle = PdfBorderStyle.Solid
lineAnnotation.lineBorder.BorderWidth = 2

# 添加到页面
page.AnnotationsWidget.Add(lineAnnotation)

# 保存文档
doc.SaveToFile("LineAnnotation.pdf")
doc.Close()

线条样式选项:

  • PdfLineEndingStyle.None - 无线端装饰
  • PdfLineEndingStyle.Butt - 平头端点
  • PdfLineEndingStyle.ClosedArrow - 闭合箭头
  • PdfLineEndingStyle.OpenArrow - 开放箭头
  • PdfLineEndingStyle.Diamond - 菱形端点
  • PdfLineEndingStyle.Circle - 圆形端点

4. 图章注释(Rubber Stamp Annotation)

图章注释用于添加预定义或自定义的状态标记,如"已批准"、"机密"、"草稿"等。

from spire.pdf import *
from datetime import datetime

# 加载 PDF 文档
document = PdfDocument()
document.LoadFromFile("document.pdf")
page = document.Pages[0]

# 创建自定义图章模板
template = PdfTemplate(150.0, 60.0)

# 设置字体和颜色
font1 = PdfTrueTypeFont("微软雅黑", 14.0, PdfFontStyle.Bold, True)
brush = PdfSolidBrush(PdfRGBColor(Color.get_Red()))

# 绘制圆角矩形边框
rectangle = RectangleF(PointF(5.0, 5.0), SizeF(140.0, 50.0))
path = PdfPath()
path.AddArc(rectangle.X, rectangle.Y, 10.0, 10.0, 180.0, 90.0)
path.AddArc(rectangle.X + rectangle.Width - 10.0, rectangle.Y, 10.0, 10.0, 270.0, 90.0)
path.AddArc(rectangle.X + rectangle.Width - 10.0, rectangle.Y + rectangle.Height - 10.0, 
            10.0, 10.0, 0.0, 90.0)
path.AddArc(rectangle.X, rectangle.Y + rectangle.Height - 10.0, 10.0, 10.0, 90.0, 90.0)
path.CloseFigure()
template.Graphics.DrawPath(PdfPen(brush, 2.0), path)

# 绘制图章文本
stampText = "✓ 已批准\n" + datetime.now().strftime("%Y-%m-%d")
template.Graphics.DrawString(stampText, font1, brush, PointF(10.0, 15.0))

# 创建图章注释
stamp = PdfRubberStampAnnotation(RectangleF(PointF(400.0, 50.0), SizeF(150.0, 60.0)))
appearance = PdfAppearance(stamp)
appearance.Normal = template
stamp.Appearance = appearance

# 设置元数据
stamp.Author = "审核人"
stamp.Subject = "文档审批"
stamp.ModifiedDate = datetime.now()

# 添加到页面
page.AnnotationsWidget.Add(stamp)

# 保存文档
document.SaveToFile("StampAnnotation.pdf")
document.Close()

预定义图章图标:

如果不想自定义图章,可以使用内置图标:

# 使用预定义的"草稿"图章
stamp = PdfRubberStampAnnotation(
    RectangleF(100.0, 100.0, 100.0, 40.0), 
    "草稿状态"
)
stamp.Icon = PdfRubberStampAnnotationIcon.Draft
stamp.Color = PdfRGBColor(Color.get_Plum())
page.AnnotationsWidget.Add(stamp)

常用预定义图标包括:

  • Draft - 草稿
  • Approved - 已批准
  • Confidential - 机密
  • Final - 最终版
  • Experimental - 实验性

5. 弹出注释(Popup Annotation)

弹出注释通常与其他注释配合使用,鼠标悬停时显示详细信息。

from spire.pdf import *

doc = PdfDocument()
page = doc.Pages.Add()

# 先创建一个文本标记
font = PdfTrueTypeFont("微软雅黑", 12.0, PdfFontStyle.Regular, True)
page.Canvas.DrawString("将鼠标悬停在注释上查看备注", font, 
                       PdfBrushes.get_Black(), 50.0, 100.0)

# 创建弹出注释
popupRect = RectangleF(PointF(100.0, 150.0), SizeF.Empty())
popupAnnotation = PdfPopupAnnotation(popupRect, "这是详细的批注信息\n可以包含多行文本")

# 设置图标样式
popupAnnotation.Icon = PdfPopupIcon.Paragraph

# 设置是否默认展开
popupAnnotation.Open = True

# 设置颜色
popupAnnotation.Color = PdfRGBColor(Color.get_Yellow())

# 添加到页面
page.AnnotationsWidget.Add(popupAnnotation)

# 保存文档
doc.SaveToFile("PopupAnnotation.pdf")
doc.Close()

6. 多边形和多段线注释(Polygon & Polyline Annotation)

多边形和多段线注释用于创建自定义形状的标注区域。

from spire.pdf import *
from datetime import datetime

doc = PdfDocument()
page = doc.Pages.Add()

# 创建多边形注释(封闭形状)
polygon = PdfPolygonAnnotation(
    page, 
    [PointF(100.0, 200.0), PointF(150.0, 180.0), PointF(200.0, 200.0), 
     PointF(180.0, 250.0), PointF(120.0, 250.0)]
)

# 设置多边形属性
polygon.Color = PdfRGBColor(Color.get_PaleVioletRed())
polygon.Text = "重点关注区域"
polygon.Author = "审稿人"
polygon.Subject = "区域标记"
polygon.BorderEffect = PdfBorderEffect.BigCloud  # 云朵边框效果
polygon.ModifiedDate = datetime.now()

# 添加到页面
page.AnnotationsWidget.Add(polygon)

# 保存文档
doc.SaveToFile("PolygonAnnotation.pdf")
doc.Close()

综合示例:创建带多种注释的审阅文档

在实际应用中,通常会组合使用多种注释类型。以下示例演示如何在一个文档中添加多种注释:

from spire.pdf import *
from datetime import datetime

# 创建文档
doc = PdfDocument()
margin = PdfMargins()
margin.Top = 50
margin.Bottom = 50
margin.Left = 50
margin.Right = 50
page = doc.Pages.Add(PdfPageSize.A4(), margin)

# 添加标题
titleFont = PdfTrueTypeFont("微软雅黑", 16.0, PdfFontStyle.Bold, True)
page.Canvas.DrawString("文档审阅示例", titleFont, 
                       PdfBrushes.get_Black(), 0.0, 30.0)

# 添加正文
contentFont = PdfTrueTypeFont("微软雅黑", 12.0, PdfFontStyle.Regular, True)
content = "这是一段需要审阅的文本内容。其中某些部分需要高亮显示,某些部分需要添加批注。"
page.Canvas.DrawString(content, contentFont, 
                       PdfBrushes.get_Black(), 0.0, 80.0)

# 1. 添加自由文本注释
freeTextRect = RectangleF(50.0, 150.0, 250.0, 60.0)
freeText = PdfFreeTextAnnotation(freeTextRect)
freeText.Text = "\n审阅意见:\n此处表述需要更加清晰明确"
freeText.Font = PdfTrueTypeFont("微软雅黑", 12.0, PdfFontStyle.Regular, True)
freeText.Color = PdfRGBColor(Color.get_LightYellow())
freeText.Opacity = 0.9
page.AnnotationsWidget.Add(freeText)

# 2. 添加图章注释
stampTemplate = PdfTemplate(120.0, 50.0, True)
stampFont = PdfTrueTypeFont("微软雅黑", 12.0, PdfFontStyle.Bold, True)
stampBrush = PdfSolidBrush(PdfRGBColor(Color.get_Red()))
stampTemplate.Graphics.DrawString("待修改", stampFont, stampBrush, PointF(10.0, 15.0))

stamp = PdfRubberStampAnnotation(RectangleF(PointF(350.0, 150.0), SizeF(120.0, 50.0)))
stampAppearance = PdfAppearance(stamp)
stampAppearance.Normal = stampTemplate
page.AnnotationsWidget.Add(stamp)

# 3. 添加线条注释指向特定位置
linePoints = [320, 200, 350, 180]
lineAnnot = PdfLineAnnotation(linePoints, "参考此处")
lineAnnot.BeginLineStyle = PdfLineEndingStyle.Butt
lineAnnot.EndLineStyle = PdfLineEndingStyle.ClosedArrow
lineAnnot.InnerLineColor = PdfRGBColor(Color.get_Blue())
page.AnnotationsWidget.Add(lineAnnot)

# 保存文档
doc.SaveToFile("ComprehensiveReview.pdf")
doc.Close()

生成结果预览:

Python创建PDF注释和标注

实用技巧

设置注释的作者和时间戳

annotation = PdfFreeTextAnnotation(rect)
annotation.Author = "张三"  # 设置作者
annotation.CreationDate = datetime.now()  # 创建时间
annotation.ModifiedDate = datetime.now()  # 修改时间

控制注释的显示层级

# 设置注释标志
annotation.Flags = PdfAnnotationFlags.Locked  # 锁定注释,防止删除
# 或使用其他标志
# PdfAnnotationFlags.Hidden - 隐藏注释
# PdfAnnotationFlags.NoView - 不显示在视图中
# PdfAnnotationFlags.ReadOnly - 只读模式

提取页面中的所有注释

# 加载文档并获取注释集合
doc = PdfDocument()
doc.LoadFromFile("annotated.pdf")
annotations = doc.Pages[0].AnnotationsWidget

# 遍历所有注释
if annotations.Count > 0:
    for i in range(annotations.Count):
        annotation = annotations.get_Item(i)
        
        # 根据类型处理不同注释
        if isinstance(annotation, PdfFreeTextAnnotationWidget):
            print(f"自由文本:{annotation.Text}")
        elif isinstance(annotation, PdfTextMarkupAnnotationWidget):
            print(f"高亮文本:{annotation.Text}")
        
        print(f"作者:{annotation.Author}")
        print(f"修改日期:{annotation.ModifiedDate}")

总结

本文介绍了使用 Python 在 PDF 文档中添加各种类型注释的方法。通过 Spire.PDF 提供的丰富 API,开发者可以:

  • 创建自由文本、高亮、线条、图章等多种注释
  • 精确控制注释的位置、颜色、透明度等属性
  • 批量处理文档审阅和标注任务
  • 提取和管理现有注释信息

这些功能使得 PDF 注释自动化成为可能,大大提高了文档协作和审阅的效率。在实际项目中,可以根据具体需求组合使用不同的注释类型,创建专业的交互式 PDF 文档。