PyMuPDF 简介
PyMuPDF是一个用于处理PDF文件的Python库,它提供了丰富的功能来操作、分析和转换PDF文档。这个库的设计目标是提供一个简单易用的API,使得开发者能够轻松地在Python程序中实现PDF文件的各种操作。
PyMuPDF的主要特点如下:
pip install pymupdf
import fitz
import PIL
# 打印pymupdf模块:基本信息
from fitz import TextPage
print(fitz.__doc__)
PyMuPDF 1.22.5: Python bindings for the MuPDF 1.22.2 library.
Version date: 2023-06-21 00:00:01.
Built for Python 3.10 on win32 (64-bit).
当使用Pixmap.pil_save()
和 Pixmap.pil_tobytes() 需要
Pillow模块
当使用Document.subset_fonts()
时需要 FontTools模块
在PyMuPDF 核心类演示涉及类
其他未使用到的其他类:Archive(档案)、Colorspace(色彩空间对象)、DisplayList(显示列表对象)、DocumentWriter(文档编辑对象)、Identity(身份对象)、 IRect(长方形对象)、linkDest(连接目的对象)、Matrix(矩阵对象)、Outline(大纲)、Quad(四边形对象)、Shape(形状对象)、 Story(章节对象)、TextPage(文本页面对象)、TextWriter(文本写入对象)、Tools(工具类)、Xml(xml 文档对象)
PyMuPDF 核心类演示
# 加载pdf 文件
doc = fitz.open("E:\doc\opencv 4.1中文官方文档v1.1版.pdf")
# 获取Document 文档对象的属性和方法
# 1、获取pdf 页数
pageCount = doc.page_count
print("pdf 页数", pageCount)
# 2、获取pdf 元数据
metaData = doc.metadata
print("pdf 元数据:", metaData)
# 3、获取pdf 目录信息
toc = doc.get_toc()
print("pdf 目录:", toc)
通过Page 对象实现以下功能:
• 您可以将页面呈现为光栅或矢量(SVG
)图像,可以选择缩放、旋转、移动或剪切页面。
• 您可以提取多种格式的页面文本和图像,并搜索文本字符串。
Page 加载方法
page = doc.load_page(pno) # loads page number 'pno' of the document (0-based)
page = doc[pno] # the short form
Documnet 迭代器加载Page 方法
for page in doc:
# do something with 'page'
# ... or read backwards
for page in reversed(doc):
# do something with 'page'
# ... or even use 'slicing'
for page in doc.pages(start, stop, step):
# do something with 'page'
# 获取Page 页面对象的属性和方法
page = doc.load_page(1) # 默认加载第一页
print("page 对象:", page)
# 1、获取Page 页面的链接、批注或表单字段
links = page.get_links()
for link in links:
# 涉及Link 对象
print("链接:", link)
annots = page.annots()
for annot in annots:
# 涉及Annot 对象
print("批注:", annot)
widgets = page.widgets()
for widget in widgets:
# 涉及表单字段
print("表单字段:", widget)
# 2、Page 页面-光栅图像
pix = page.get_pixmap()
print("打印页面图像对象:", pix)
# 保存光栅图像图像,需要依赖第三方框架:Pillow
pix.pil_save("page-%i.png" % page.number)
Page.get_pixmap()
提供了许多用于控制图像的变体:分辨率、颜色空间(例如,生成灰度图像或具有减色方案的图像)、透明度、旋转、镜像、移位、剪切等。
Pixmap
包含以下引用的许多方法和属性。其中包括整数宽度、高度(每个像素)和跨距(一个水平图像行的字节数)。属性示例表示表示图像数据的矩形字节区域(Python字节对象)。
温馨提示:page.get_svg_image()
创建页面的矢量图像。
# 3、Page 获取文本\图像\其他信息
# 温馨提示:涉及TextPage 常量类型定义
text = page.get_text("text")
print("指定页面文本内容:", text)
对opt
使用以下字符串之一以获取不同的格式:
"text"
:(默认)带换行符的纯文本。无格式、无文字位置详细信息、无图像- "blocks"
:生成文本块(段落)的列表- "words"
:生成单词列表(不包含空格的字符串)- "html"
:创建页面的完整视觉版本,包括任何图像。这可以通过internet浏览器显示- "dict"/"json"
:与HTML
相同的信息级别,但作为Python字典或resp.JSON
字符串。- "rawdict"/"rawjson"
:"dict"/"json"
的超级集合。它还提供诸如XML
之类的字符详细信息。- "xhtml"
:文本信息级别与文本版本相同,但包含图像。- "xml"
:不包含图像,但包含每个文本字符的完整位置和字体信息。使用XML
模块进行解释。# 4、Page 文本检索
search = page.search_for("图像的基本操作")
print("打印检索文本的位置:", search)
提供一个矩形列表,每个矩形都包含一个字符串“mupdf”
(不区分大小写)。
PDF
是唯一可以使用PyMuPDF
修改的文档类型。其他文件类型是只读的。但是,您可以将任何文档(包括图像)转换为PDF,然后将所有PyMuPDF
功能应用于转换果,Document.convert_to_pdf()
。
Document.save()
始终将PDF以其当前(可能已修改)状态存储在磁盘上。
通常,您可以选择是保存到新文件,还是仅将修改附加到现有文件(“增量保存”),这通常要快得多。
# Document 操作PDF页面
# 1、PDF 页面删除
# doc.delete_page(1)
# 1、PDF 页面拷贝和移动
doc.copy_page(1) # 第一页移动最后一页,温馨提示:移动的页面还在元PDF 文件中。
# 1、 PDF 插入页面, 返回插入页面对象
new_page = doc.new_page(pno=-1, width=595, height=842)
# 插入页面, 设置文本
text = "你的文本"
point = fitz.Point(50, 50) # 这是一个下x,y 二维坐标系,在这个区域内插入你的文本
new_page.insert_text(point, text, fontsize=20)
# 2、Document 保存
doc.save("opencv pdf文件调整.pdf")
# 3、Documemt 销毁
doc.close()
PDF 删除方法
Document.delete_page()
Document.delete_pages()
PDF移动拷贝方法
Document.copy_page()
Document.fullcopy_page()
Document.move_page()
PDF插入Page 方法
Document.insert_page()
Document.new_page()
def split_per_page(input, output):
if not os.path.exists(output):
os.makedirs(output)
doc = fitz.open(input)
for page in range(doc.page_count):
dst_doc = fitz.open()
dst_doc.insert_pdf(doc,from_page=page,to_page=page)
dst_doc.save(os.path.join(output,f'{page}.pdf'))
dst_doc.close()
doc.close()
# 把每一个页面保存为一个pdf,并保存在test文件夹中
split_per_page("test.pdf","test")
def split_range_page(input, output, range):
if not os.path.exists(output):
os.makedirs(output)
doc = fitz.open(input)
start = range[0] - 1
end = range[1] - 1
dst_doc = fitz.open()
dst_doc.insert_pdf(doc, from_page=start, to_page=end)
dst_doc.save(os.path.join(output,'range_page.pdf'))
dst_doc.close()
doc.close()
# 把1-10也保存为pdf,保存在test文件夹中
split_range_page('test.pdf','test', [1,10])
def split_selected_page(input, output, pages):
if not os.path.exists(output):
os.makedirs(output)
doc = fitz.open(input)
result = map(lambda x: x - 1, pages)
doc.select(list(result))
doc.save(os.path.join(output,'selected_pages.pdf'))
doc.close()
# 把第一、三、八页面保存为pdf,并保存在test文件夹中
split_selected_page('test.pdf','test',[1,3, 8])
import fitz
doc_a = fitz.open("a.pdf") # open the 1st document
doc_b = fitz.open("b.pdf") # open the 2nd document
doc_a.insert_pdf(doc_b) # merge the docs
doc_a.save("a+b.pdf") # save the merged document with a new filename
# 把b.pdf合并到a.pdf,保存为a+b.pdf
import fitz
doc = fitz.open("test.pdf") # open a document
for page_index in range(len(doc)): # iterate over pdf pages
page = doc[page_index] # get the page
image_list = page.get_images()
# print the number of images found on the page
if image_list:
print(f"Found {len(image_list)} images on page {page_index}")
else:
print("No images found on page", page_index)
for image_index, img in enumerate(image_list, start=1): # enumerate the image list
xref = img[0] # get the XREF of the image
pix = fitz.Pixmap(doc, xref) # create a Pixmap
if pix.n - pix.alpha > 3: # CMYK: convert to RGB first
pix = fitz.Pixmap(fitz.csRGB, pix)
pix.save("page_%s-image_%s.png" % (page_index, image_index)) # save the image as png
pix = None
def covert2pic(zoom):
doc = fitz.open("test.pdf")
total = doc.page_count
for pg in range(total):
page = doc[pg]
zoom = int(zoom) #值越大,分辨率越高,文件越清晰
rotate = int(0)
trans = fitz.Matrix(zoom / 100.0, zoom / 100.0).prerotate(rotate)
pm = page.get_pixmap(matrix=trans, alpha=False)
lurl='.pdf/%s.jpg' % str(pg+1)
pm.save(lurl)
doc.close()
covert2pic(200)
def add_watermark(input, watermark):
doc = fitz.open(input)
for page in doc:
page.insert_image(page.bound(),filename=watermark, overlay=False)
doc.save(os.path.join("test","watermark.pdf"))
doc.close()
add_watermark("test.pdf","watermark.png")
PDF加密有两种形式
def encrypt_pdf():
perm = int(
fitz.PDF_PERM_ACCESSIBILITY # always use this
| fitz.PDF_PERM_PRINT # permit printing
| fitz.PDF_PERM_COPY # permit copying
| fitz.PDF_PERM_ANNOTATE # permit annotations
) # 可以打印,复制,添加注释
owner_pass = "owner" # owner password
user_pass = "user" # user password
encrypt_meth = fitz.PDF_ENCRYPT_AES_256 # strongest algorithm
doc = fitz.open("test.pdf") # empty pdf
doc.save("encrypt.pdf",encryption=encrypt_meth,owner_pw=owner_pass,permissions=perm,user_pw=user_pass) # 同时使用
# 这两个加密方式可以,单独使用,也可以同时使用
# 单独使用用户加密
doc.save("encrypt.pdf",encryption=encrypt_meth,owner_pw=owner_pass)
功能要求:在PyQT-5 展示pdf 文件.
效果展示:
PyQT-5 UI效果展示和源文件
pdfshow.ui
Form
0
0
400
300
Form
130
70
54
12
PDF展示
pdfshow.py 源码
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'pdfshow.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QImage, QPixmap, QTransform
from PyQt5.QtWidgets import QWidget, QApplication
# 添加PDF 文件操作依赖
import fitz
class Ui_Form(QWidget):
def __init__(self):
super().__init__()
self.label = None
self.setupUi()
self.image()
def setupUi(self):
self.setObjectName("Form")
self.resize(400, 300)
self.label = QtWidgets.QLabel(self)
self.label.setGeometry(QtCore.QRect(130, 70, 54, 12))
self.label.setObjectName("label")
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self):
_translate = QtCore.QCoreApplication.translate
self.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "PDF展示"))
def image(self):
file = "E:\doc\opencv 4.1中文官方文档v1.1版.pdf"
# 打开文件
doc = fitz.open(file)
# 读取一页 0代表第1页
page_one = doc.load_page(1)
# 将第一页转换为Pixmap
page_pixmap = page_one.get_pixmap()
# 将Pixmap转换为QImage
image_format = QImage.Format_RGBA8888 if page_pixmap.alpha else QImage.Format_RGB888
page_image = QImage(page_pixmap.samples, page_pixmap.width,
page_pixmap.height, page_pixmap.stride, image_format)
width = page_image.width()
height = page_image.height()
# QImage 转为QPixmap
pix = QPixmap.fromImage(page_image)
trans = QTransform()
trans.rotate(90) # 这里设置旋转角度
new = pix.transformed(trans)
# 设置标签宽和高
self.label.setFixedSize(400, 350)
# 设置图片大小自适应标签
self.label.setScaledContents(True)
# 给标签设置图像
self.label.setPixmap(new)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Ui_Form()
w.show()
sys.exit(app.exec_())
解决思路