当前位置: 首页 > 工具软件 > PyPDF2 > 使用案例 >

Python系列 之 PyPDF2库

范文昌
2023-12-01

Python系列 之 PyPDF2库 学习

PyPDF2中主要涉及到的几个对象有 PdfFileReader、PdfFileWriter和PdfFileMerger以及PageObject

PdfFileReader

PdfFileReader对象:

import PyPDF2
PyPDF2.PdfFileReader(stream , strict=True , warndest=None , overwriteWarnings=True))
# 参数
# stream :一个 File 对象或支持类似于 File 对象;也可以是表示 PDF 文件路径的字符

# 初始化一个Reader对象
# pdfReader = PyPDF2.PdfFileReader(stream=open(file='pdf2.pdf', mode='rb'))
pdfReader = PyPDF2.PdfFileReader('pdf2.pdf')

PdfFileReader对象的一些属性和方法:

属性说明
documentInfo获取PDF文件的文档信息字典
isEncryptedPDF文件是否加密
numPages返回PDF文件的页数
pages相当于返回PDF文件所有页面,每个页面pageObject对象的列表
pageLayout获取PDF文件的页面布局
pageMode获取PDF文件的页面模式
xmpMetadata从PDF文件根目录检索XMP数据
方法说明
decrypt(password)解密
getDocumentInfo()同documentInfo属性
getNumPages()同numPages 属性
getPage(pageNumber)获取PDF文件中第pageNumber+1页的PageObject对象 pageNumber基于0
getPageLayout()同pageLayout属性
getPageMode()同pageMode属性
getPageNumber(page)获取 PageObject对象所在PDFFileReader对象的页数
getXmpMetadata()同xmpMetadata属性

简单示例:

# 返回 PDF 文件的文档信息字典
print('PDF 文件的文档信息字典:', pdfReader.getDocumentInfo(), pdfReader.documentInfo)

# 返回PDF文件的页数
print('PDF文件的页数:', pdfReader.getNumPages(), pdfReader.numPages)

# PageObject = PdfFileReader.getPage(pageNumber)
# 获取PdfFileReader中第pageNumber+1页的PageObject对象  pageNumber基于0
page_obj = pdfReader.getPage(1)
print(type(page_obj))

# 获取 PageObject对象 所在PDFFileReader对象的页数 如果找不到页面 返回 -1
print('page_obj所在的页数:', pdfReader.getPageNumber(page=page_obj))

# 获取页面布局 返回当前使用的页面布局
print('获取页面布局:', pdfReader.getPageLayout())

# 获取页面模式 返回 当前使用的页面模式
print('获取页面模式:', pdfReader.getPageMode())

# 从 PDF 文档根目录检索 XMP 数据
print('检索 XMP 数据:', pdfReader.getXmpMetadata())

# 判断该PDF是否加密
print('判断该PDF是否加密:', pdfReader.isEncrypted)

# PDFFileReader的每页pageObject的list?
print(type(pdfReader.pages))

PdfFileWriter

PyPDF2.PdfFileWriter
PdfFileWriter 用于写出PDF文件,通常由PdfFileReader生成的页面

import PyPDF2
pdfWriter = PyPDF2.PdfFileWriter()

主要方法:

方法说明
addPage(page)向此 PdfFileWriter 添加页面 该页面通常是从一个PdfFileReader实例中获取的
addBlankPage(width=None, height=None)追加一个空白页
insertBlankPage(width=None, height=None, index=0)将空白页插入此PdfFileWriter的指定页码并返回此页面的PageObject对象
insertPage(page, index=0)在此 PdfFileWriter中的指定位置插入一个pageObject对象,该页面通常是从一个 PdfFileReader实例中获取的,默认在最开始插入
getNumPages()获取PdfFileWrite中已有pageObject的页数
getPage(pageNumber)获取PdfFileWrite中指定页码的pageObject对象
addAttachment(fname, fdata)在PdfFileWriter 中嵌入文件
addBookmark(title, pagenum, parent=None, color=None, bold=False, italic=False, fit=’/Fit’, *args)添加书签
addJS(javascript)添加javascript代码
addLink(pagenum, pagedest, rect, border=None, fit=’/Fit’, *args)添加 超链接
addMetadata(infos)添加 Metadata
encrypt(user_pwd, owner_pwd=None, use_128bit=True)添加密码
removeImages(ignoreByteStringObject=False)从此PdfFileWriter中删除图像
removeLinks()从此PdfFileWriter中删除链接和注释
setPageLayout(layout)设置页面布局
getPageLayout()获取页面布局 PdfFileWriter.pageLayout
setPageMode(mode)设置页面模式 对应属性 PdfFileWriter.pageMode
getPageMode()获取页面模式
write(stream)将添加到PdfFileWriter对象的所有页面 写入PDF文件

示例代码:

addPage 方法

# addPage 向此 PDF 文件添加页面 该页面通常是从一个PdfFileReader实例中获取的
for page in pdfReader.pages:
    pdfWriter.addPage(page)

addBlankPage方法:

# addBlankPage(width=None, height=None) 追加一个空白页,如果没有指定width|height,则使用上一页的width|height
# 如果没有指定width|height并且也没有上一页 raise PageSizeNotDefinedError
pdfWriter.addBlankPage(width=None, height=None)

insertBlankPage方法:

# insertBlankPage 将空白页插入此 PDF 文件并返回此页面的PageObject对象
# insertBlankPage(width=None, height=None, index=0) 默认在最开始添加
pdfWriter.insertBlankPage()

insertPage方法:

# insertPage(page, index=0)
# 在此 PDF 文件中插入一个pageObject对象。该页面通常是从一个 PdfFileReader实例中获取的
# index指定插入位置 默认再最开始插入
# page_obj 从PdfFileReader中获取
pdfWriter.insertPage(page=page_obj, index=0)

getNumPages方法:

# getNumPages() PDF文件页数
print(pdfWriter.getNumPages())

getPage方法:

# getPage(pageNumber) 获取PdfFileWriter中第pageNumber+1页的PageObject对象  pageNumber基于0
page_obj_f_writer = pdfWriter.getPage(0)

addAttachment方法:

# addAttachment(fname, fdata) 在 PDF 中嵌入文件
# pdfWriter.addAttachment(fname="附件一.txt", fdata=b'Hello world!')
pdfWriter.addAttachment(fname="Attachment.txt", fdata=('Hello world!').encode(encoding='UTF-8'))

addBookmark方法:

# addBookmark(title, pagenum, parent=None, color=None, bold=False, italic=False, fit='/Fit', *args) 添加书签
# Parameters:
# title 书签的标题
# pagenum 书签对应的页码
# parent 对父书签的引用以创建嵌套书签
# color (tuple) 书签的颜色  Color of the bookmark as a red, green, blue tuple from 0.0 to 1.0
# bold (bool)  字体是否粗体
# italic (bool) 字体是否斜体
# fit 页面适合或“缩放”选项
pdfWriter.addBookmark(title="Mark", pagenum=0, color=(0.0, 0.5, 1.0), bold=True, italic=True, fit='/Fit')

addJS方法:

# addJS(javascript) 打开PDF时运行javascript代码 官网实例
pdfWriter.addJS("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")

addLink 方法:

# addLink 添加从矩形区域到指定页面的内部链接 超链接?
# addLink(pagenum, pagedest, rect, border=None, fit='/Fit', *args)
# Parameters:
# pagenum (int) 放置链接的页面的索引
# pagedest (int) 链接指向的页面的索引
# rect   RectangleObject对象  or array of four integers specifying the clickable rectangular area [xLL, yLL, xUR, yUR],
# or string in the form "[ xLL yLL xUR yUR ]".
# border 描述边框绘制的数组
# fit (str) 页面适合或“缩放”选项 默认 '/Fit'
# fit 取值:
# /Fit	No additional arguments
# /XYZ	[left] [top] [zoomFactor]
# /FitH	[top]
# /FitV	[left]
# /FitR	[left] [bottom] [right] [top]
# /FitB	No additional arguments
# /FitBH	[top]
# /FitBV	[left]

# from PyPDF2.generic import RectangleObject
# pdfWriter.addLink(pagenum=2, pagedest=1, rect=RectangleObject([100, 100, 600, 800]))
pdfWriter.addLink(pagenum=0, pagedest=1, rect=[100, 100, 600, 800])

addMetadata方法:

# addMetadata(infos) 添加 Metadata
# infos 一个Python字典,其中每个键是一个字段,每个值是Metadata
pdfWriter.addMetadata(infos={'/Producer': 'Mark'})

encrypt方法:

# encrypt 使用 PDF 标准加密处理程序加密此 PDF 文件
# encrypt(user_pwd , owner_pwd=None , use_128bit=True)
pdfWriter.encrypt(user_pwd='password', owner_pwd='password')

write方法:

# write(stream) 将添加到PdfFileWriter对象的所有页面 写入PDF文件
with open('output.pdf', mode='wb') as output:
    pdfWriter.write(output)

PdfFileMerger

PdfFileMerger对象可以将多个PDF文件通过任意组合合并到一起;是专门用来将多个PDF进行合并的,PdfFileMerger对象能实现的基本上PdfFileWriter对象也能实现

初始化PdfFileMerger对象:

import PyPDF2
# PyPDF2.PdfFileMerger(strict=True)
# PdfFileMerger对象可以将多个PDF文件通过任意组合合并到一起
# 初始化PdfFileMerger对象
pdfMerger = PyPDF2.PdfFileMerger(strict=False)

常用方法:

方法说明
append(fileobj, bookmark=None, pages=None, import_bookmarks=True)将fileobj所有页面连接到文件末尾
merge(position, fileobj, bookmark=None, pages=None, import_bookmarks=True)将给定fileobj中的页面合并到指定页码
write(fileobj)将所有已合并的数据写入fileobj文件
close()关闭并清除所有内存使用
addBookmark(title, pagenum, parent=None)添加书签
addMetadata(infos)添加Metadata
setPageLayout(layout)设置页面布局
setPageMode(mode)设置页面模式
addNamedDestination

代码示例:

append方法:

# 向PdfFileMerger对象末尾添加PDF文件
# append(fileobj, bookmark=None, pages=None, import_bookmarks=True)
# 直接指定PDF文件的路径追加到pdfMerger
pdfMerger.append(fileobj='pdf3.pdf')
# 使用PdfFileReader对象进行追加
pdfMerger.append(pdfReader)
# write(fileobj)
pdfMerger.write('output.pdf')
# close()
# 关闭所有文件描述符(输入和输出)并清除所有内存使用
pdfMerger.close()

merge方法:

# merge(position, fileobj, bookmark=None, pages=None, import_bookmarks=True)
# 参数 :
# position 合并到PdfFileMerger对象的位置
# fileobj 要合并的PDF文件或者PdfFileReader对象
# pages 一个tuple 表示要合并的fileobj的页码范围
pdfMerger.merge(position=1, fileobj=pdfReader, pages=(0, 1))
# write(fileobj)
pdfMerger.write('output.pdf')
# close()
# 关闭所有文件描述符(输入和输出)并清除所有内存使用
pdfMerger.close()

PageObject

PageObject对象表示 PDF 文件中的单个页面,PageObject对象的一些方法主要来实现对PDF页面进行操作,比如添加水印,页面的旋转,缩放等功能
PageObject对象通常通过访问PdfFileReader对象的 getPage()方法来生成:

import PyPDF2
# PyPDF2.pdf.PageObject
# PyPDF2.pdf.PageObject(pdf=None,indirectRef=None)
pdf_reader_1 = PyPDF2.PdfFileReader(stream="pdf1.pdf")
page_obj_1 = pdf_reader_1.getPage(0)

常用的一些方法:

方法说明
extractText()提取页面文本
getContents()返回页面内容
mergePage(page2)将两个页面的内容合并为一个,可以实现水印效果
mergeRotatedPage(page2, rotation, expand=False)类似mergePage方法,可以对page2页面进行旋转操作
mergeScaledPage(page2, scale, expand=False)类似mergePage方法,可以对page2页面进行缩放操作
mergeTranslatedPage(page2, tx, ty, expand=False)类似mergePage方法,可以对page2页面进行平移操作
mergeRotatedScaledPage(page2, rotation, scale, expand=False)类似mergePage方法,可以对page2页面进行旋转以及缩放操作
mergeRotatedScaledTranslatedPage(page2, rotation, scale, tx, ty, expand=False)类似mergePage方法,可以对page2页面进行旋转缩放以及平移操作
mergeRotatedTranslatedPage(page2, rotation, tx, ty, expand=False)类似mergePage方法,可以对page2页面进行旋转以及平移操作
mergeScaledTranslatedPage(page2, scale, tx, ty, expand=False)类似mergePage方法,可以对page2页面进行缩放以及平移操作
mergeTransformedPage(page2, ctm, expand=False)类似mergePage方法,可以对page2页面进行矩阵转换操作
rotateClockwise(angle)顺时针旋转页面,angle必须是 90 度的增量
rotateCounterClockwise(angle)逆时针旋转页面,angle必须是 90 度的增量
scale(sx, sy)缩放页面
scaleBy(factor)按固定XY轴比例缩放页面
scaleTo(width, height)页面缩放到指定尺寸
addTransformation(ctm)将转换矩阵应用于页面

实例

最后附上一个实例:
获取某目录下所有PDF文件 合并到一个PDF文件 并为合并后的PDF文件所有页面添加水印

import os
import PyPDF2


def get_PDFs(path):
    """
    :param path: 需要合并的PDF文件所在路径
    :return: 路径下所有PDF文件的路径list
    """
    return [os.path.join(path, x) for x in os.listdir(path) if os.path.splitext(x)[-1] == '.pdf']


def merge_pdf(output_pdf, page2_pdf, *pdf_objs):
    """
    获取某目录下所有PDF文件 合并到一个PDF文件 并为合并后的PDF文件所有页面添加水印
    :param output_pdf: 合并后的PDF文件
    :param page2_pdf: 水印模板PDF文件
    :param pdf_objs:需要合并的所有PDF文件
    :return:None
    """
    output_path = os.path.dirname(output_pdf)
    if not os.path.exists(output_path):
        os.makedirs(output_path, exist_ok=True)
    pdf_writer = PyPDF2.PdfFileWriter()
    pdf_reader = PyPDF2.PdfFileReader(stream=page2_pdf)
    # 获取水印模板PDF文件对应的pageObject对象
    page2 = pdf_reader.getPage(0)
    for pdf in pdf_objs:
        pdf_reader = PyPDF2.PdfFileReader(stream=pdf)
        for page in pdf_reader.pages:
            # 添加水印
            merge_page(page, page2)
            # 添加水印后的页面添加到PdfFileWriter
            pdf_writer.addPage(page)
    with open(output_pdf, "wb") as output:
        pdf_writer.write(output)


def merge_page(page, page2):
    """
    :param page: 需要添加水印的PDF页面
    :param page2: 水印模板
    :return:None
    """
    page.mergeRotatedScaledTranslatedPage(page2, rotation=45, scale=0.5, tx=100, ty=100, expand=True)


if __name__ == '__main__':
    pdf_objs = get_PDFs('./')
    output_pdf = "./output/output.pdf"
    page2_pdf = "pdf1.pdf"
    merge_pdf(output_pdf, page2_pdf, *pdf_objs)

主要参考:PyPDF2 文档

以上就是对PyPDF2库的学习
如果有什么不对的地方,欢迎指正!

 类似资料: