系列文章:
Python PDF神器PyMuPDF使用指南 (一)——安装和基础功能
Python PDF神器PyMuPDF使用指南 (二)——文件和文本功能
Python PDF神器PyMuPDF使用指南 (三)——图像和注释功能
Python PDF神器PyMuPDF使用指南 (四)——绘图、多线程和OCR功能
Python PDF神器PyMuPDF使用指南 (五)——命令行使用
Python PDF神器PyMuPDF使用指南 (六)——Document类详解
Python PDF神器PyMuPDF使用指南 (七)——Page类详解
Python PDF神器PyMuPDF使用指南 (八)——基础使用指南
正文:
PyMuPDF是一个高性能的Python库,用于PDF(和其他)文档的数据提取、分析、转换和操作。
Github地址为:pymupdf代码库
官方文档地址为:PyMuPDF文档
前面几篇文章详细介绍了PyMuPDF的主要功能以及命令行的使用,本文将开始介绍PyMuPDF做为Python库调用的主要类和方法。不过篇幅原因,估计只能详细介绍一部分,下一篇文章会继续介绍。
这个类表示一个文档。它可以通过文件或内存来构建,并对文档进行各种操作。
这个类有别名open
,即pymupdf.Document(...)
和pymupdf.open(...)
是等效的。
注意“”
从v1.17.0版本开始,仅支持对EPUB文件的全新页面定位机制。该文档类型内部按章节组织,页面可以通过其所谓的“位置”来高效查找。位置是一个元组(章节,页码),由章节号和该章节中的页码组成。两个数字都是基于零的。
虽然仍然可以通过页面的(绝对)编号定位页面,但这可能意味着必须先布局整个EPUB文档才能定位该页面。如果文档非常大,这可能会显著影响性能。使用页面的(章节,页码)可以避免这种情况。
为了保持一致的API,PyMuPDF支持所有文件类型的页面位置语法——没有此功能的文档则只有一个章节。Document.load_page()
和等效的索引访问现在也支持位置参数。
有很多方法可以在页面编号和位置之间进行转换,用于确定章节数量、每个章节的页面数量、计算下一个和前一个位置,以及文档的最后一个页面位置。
Document.add_layer()
:仅限PDF:创建新的可选内容配置Document.add_ocg()
:仅限PDF:添加新的可选内容组Document.authenticate()
:访问加密文档Document.bake()
:仅限PDF:将注释/字段转化为永久内容Document.can_save_incrementally()
:检查是否可以增量保存Document.chapter_page_count()
:章节中的页面数量Document.close()
:关闭文档Document.convert_to_pdf()
:将文档转换为PDF格式并写入内存Document.copy_page()
:仅限PDF:复制页面引用Document.del_toc_item()
:仅限PDF:删除单个目录项Document.delete_page()
:仅限PDF:删除页面Document.delete_pages()
:仅限PDF:删除多页Document.embfile_add()
:仅限PDF:从缓冲区添加新嵌入文件Document.embfile_count()
:仅限PDF:嵌入文件的数量Document.embfile_del()
:仅限PDF:删除嵌入文件条目Document.embfile_get()
:仅限PDF:提取嵌入文件缓冲区Document.embfile_info()
:仅限PDF:获取嵌入文件的元数据Document.embfile_names()
:仅限PDF:列出嵌入文件Document.embfile_upd()
:仅限PDF:修改嵌入文件Document.extract_font()
:仅限PDF:按xref提取字体Document.extract_image()
:仅限PDF:按xref提取嵌入的图像Document.ez_save()
:仅限PDF:默认不同的保存文档Document.find_bookmark()
:查找书签并返回其页面位置Document.fullcopy_page()
:仅限PDF:复制页面Document.get_layer()
:仅限PDF:列出OCG的状态(开、关、待渲染组)Document.get_layers()
:仅限PDF:列出可选内容配置Document.get_oc()
:仅限PDF:获取OCG/OCMD xref的图像/表单xobjectDocument.get_ocgs()
:仅限PDF:获取所有可选内容组信息Document.get_ocmd()
:仅限PDF:获取OCMD的定义Document.get_page_fonts()
:仅限PDF:列出页面引用的字体Document.get_page_images()
:仅限PDF:列出页面引用的图像Document.get_page_labels()
:仅限PDF:列出页面标签定义Document.get_page_numbers()
:仅限PDF:获取具有指定标签的页面编号Document.get_page_pixmap()
:根据页面编号创建页面图像Document.get_page_text()
:提取指定页面的文本Document.get_page_xobjects()
:仅限PDF:列出页面引用的XObjectDocument.get_sigflags()
:仅限PDF:确定签名状态Document.get_toc()
:提取目录Document.get_xml_metadata()
:仅限PDF:读取XML元数据Document.has_annots()
:仅限PDF:检查文档是否包含注释Document.has_links()
:仅限PDF:检查文档是否包含链接Document.insert_page()
:仅限PDF:插入新页面Document.insert_pdf()
:仅限PDF:从另一个PDF插入页面Document.insert_file()
:仅限PDF:从任意文档插入页面Document.journal_can_do()
:仅限PDF:哪些操作可以在文档中进行Document.journal_enable()
:仅限PDF:启用文档的日志功能Document.journal_load()
:仅限PDF:从文件加载日志Document.journal_op_name()
:仅限PDF:返回日志步骤的名称Document.journal_position()
:仅限PDF:返回日志状态Document.journal_redo()
:仅限PDF:重做当前操作Document.journal_save()
:仅限PDF:保存日志到文件Document.journal_start_op()
:仅限PDF:开始“操作”并为其命名Document.journal_stop_op()
:仅限PDF:结束当前操作Document.journal_undo()
:仅限PDF:撤销当前操作Document.layer_ui_configs()
:仅限PDF:列出可选内容的意图配置Document.layout()
:重新分页文档(如果支持)Document.load_page()
:读取页面Document.make_bookmark()
:在可重排文档中创建页面指针Document.move_page()
:仅限PDF:移动页面到文档中的不同位置Document.need_appearances()
:仅限PDF:获取/设置NeedAppearances属性Document.new_page()
:仅限PDF:插入新空白页面Document.next_location()
:返回下一页的位置(章节,页码)Document.outline_xref()
:仅限PDF:目录项的xrefDocument.page_cropbox()
:仅限PDF:页面的未旋转矩形区域Document.page_xref()
:仅限PDF:页面编号的xrefDocument.pages()
:页面范围的迭代器Document.pdf_catalog()
:仅限PDF:xref of catalog (root)Document.pdf_trailer()
:仅限PDF:文档的尾部源Document.prev_location()
:返回前一页的位置(章节,页码)Document.reload_page()
:仅限PDF:提供页面的新副本Document.resolve_names()
:仅限PDF:将目标名称转换为Python字典Document.save()
:仅限PDF:保存文档Document.saveIncr()
:仅限PDF:增量保存文档Document.scrub()
:仅限PDF:去除敏感数据Document.search_page_for()
:在页面上搜索字符串Document.select()
:仅限PDF:选择页面的子集Document.set_layer_ui_config()
:仅限PDF:暂时设置OCG的可见性Document.set_layer()
:仅限PDF:批量改变OCG的状态Document.set_markinfo()
:仅限PDF:设置MarkInfo值Document.set_metadata()
:仅限PDF:设置元数据Document.set_oc()
:仅限PDF:将OCG/OCMD附加到图像/表单xobjectDocument.set_ocmd()
:仅限PDF:创建或更新OCMDDocument.set_page_labels()
:仅限PDF:添加/更新页面标签定义Document.set_pagemode()
:仅限PDF:设置页面模式Document.set_pagelayout()
:仅限PDF:设置页面布局Document.set_toc_item()
:仅限PDF:修改单个目录项Document.set_toc()
:仅限PDF:设置目录Document.set_xml_metadata()
:仅限PDF:创建或更新XML元数据Document.subset_fonts()
:仅限PDF:创建字体子集Document.switch_layer()
:仅限PDF:激活OC配置Document.tobytes()
:仅限PDF:将文档写入内存Document.xref_copy()
:仅限PDF:将PDF字典复制到另一个xrefDocument.xref_get_key()
:仅限PDF:获取字典键的值Document.xref_get_keys()
:仅限PDF:列出xref对象的键Document.xref_object()
:仅限PDF:获取xref对象的定义源__init__(self, filename=None, stream=None, *, filetype=None, rect=None, width=0, height=0, fontsize=11)
自 v1.14.13 起:支持 io.BytesIO
用于内存中的文档。
自 v1.19.6 起:更清晰、更简洁且一致的异常信息。如果未指定文件类型,始终假定文件类型为“pdf”。空文件和内存区域将始终引发异常。
用于创建一个 Document
对象。
在默认参数下,将创建一个新的空 PDF 文档。
stream
,则从内存中创建文档,如果它不是 PDF,则 filename
或 filetype
必须指明其类型。stream
为 None
,则从指定的 filename
文件创建文档,其类型通过扩展名推断。也可以通过 filetype
来覆盖此行为。参数说明:
pathlib
对象,表示文件路径。文档类型通过文件名扩展名推断。如果没有提供或扩展名不匹配支持的类型,则假定为 PDF 文档。对于内存文档,可以使用此参数代替 filetype
(见下文)。filename
或 filetype
指定。application/pdf
这样的 MIME 类型。像 "pdf" 或 ".pdf" 的字符串也可以使用。对于 PDF 文档,可以省略此参数;否则,必须匹配支持的文档类型。fontsize
参数一起,每个页面将根据该布局进行排版,并且还会决定页面数量。height
一起使用,作为 rect
的替代方案来指定布局信息。width
一起使用,作为 rect
的替代方案来指定布局信息。rect
或 width
和 height
参数,则忽略此参数。此参数用于计算页面布局。异常:
RuntimeError
的子类。FileDataError
和 RuntimeError
的子类。RuntimeError
的子类。返回:
返回一个文档对象。如果无法创建文档,则会按上述顺序抛出异常。请注意,PyMuPDF 特定的异常 FileNotFoundError
、EmptyFileError
和 FileDataError
会在检查 RuntimeError
时被拦截。
遇到问题时,可以查看更详细的内部消息存储:print(pymupdf.TOOLS.mupdf_warnings())
(此调用将清空警告,但也可以防止清空——请参考 Tools.mupdf_warnings()
)。
注意:并非所有文档类型在打开时都检查其有效格式。例如,光栅图像将在稍后访问其内容时才会抛出异常。其他类型(尤其是具有非二进制内容的类型)也可以被成功打开(有时甚至在格式内容无效的情况下):
HTM, HTML, XHTML:始终可以打开,metadata["format"]
将分别为“HTML5”和“XHTML”。
XML, FB2:始终可以打开,metadata["format"]
为“FictionBook2”。
可能的打开方式概览:
>>> # from a file
>>> doc = pymupdf.open("some.xps")
>>> # handle wrong extension
>>> doc = pymupdf.open("some.file", filetype="xps")
>>>
>>> # from memory, filetype is required if not a PDF
>>> doc = pymupdf.open("xps", mem_area)
>>> doc = pymupdf.open(None, mem_area, "xps")
>>> doc = pymupdf.open(stream=mem_area, filetype="xps")
>>>
>>> # new empty PDF
>>> doc = pymupdf.open()
>>> doc = pymupdf.open(None)
>>> doc = pymupdf.open("")
注意:光栅图像即使文件扩展名错误(但仍是支持的类型)也不会有问题。MuPDF 会在实际访问文件内容时确定正确的图像类型并处理它。因此, pymupdf.open("file.jpg")
即使是 PNG 图像也能正常工作。
Document
类还可以作为上下文管理器使用。在退出时,文档会自动关闭。
>>> import pymupdf
>>> with pymupdf.open(...) as doc:
for page in doc: print("page %i" % page.number)
page 0
page 1
page 2
page 3
>>> doc.is_closed
True
>>>
get_oc(xref)
(新功能:v1.18.4)
返回与图像或表单 XObject 关联的 OCG 或 OCMD 的交叉引用号。
参数:
Document.get_page_images()
或 Document.get_page_xobjects()
获取。如果是无效的交叉引用号,将引发异常。返回:
set_oc(xref, ocxref)
(新功能:v1.18.4)
如果 xref
代表一个图像或表单 XObject,设置或移除其关联的可选内容对象的交叉引用号。
参数:
get_layers()
(新功能:v1.18.3)
显示可选层配置。始终存在一个标准层,不会包含在响应中。
>>> for item in doc.get_layers(): print(item)
{'number': 0, 'name': 'my-config', 'creator': ''}
>>> # use 'number' as config identifier in add_ocg
add_layer(name, creator=None, on=None)
(新功能:v1.18.3)
添加一个可选内容配置。层配置作为 ON/OFF 状态的集合,可以在文档中快速切换不同的视图。
参数:
switch_layer(number, as_default=False)
(新功能:v1.18.3)
切换到由指定可选层配置定义的文档视图。此切换是临时的,除非将其设为默认视图。
参数:
Document.layer_configs()
。True
,则将此配置设为默认配置。add_ocg(name, config=-1, on=True, intent='View', usage='Artwork')
(新功能:v1.18.3)
添加一个可选内容组(OCG)。OCG 是决定对象可见性的最重要单位。对于 PDF,必须至少存在一个 OCG 才能被视为具有可选内容。
参数:
返回:
返回创建的 OCG 的交叉引用号。可以用作在支持的对象中作为 oc
参数的入口。
注意:可以创建多个具有相同参数的 OCG,它们不会导致问题。 Document.save()
的垃圾选项 3 将删除任何重复项。
新增于 v1.18.4
创建或更新 OCMD(可选内容成员字典)。
参数:
"AnyOn"
(默认)、"AnyOff"
、"AllOn"
、"AllOff"
(支持大小写)。ocgs
和 policy
的替代方法。返回类型:
int
:返回 OCMD 的 xref。可以将其作为 oc=xref
参数,传递给支持的对象,进一步用于 Document.set_oc()
或 Annot.set_oc()
。注意:OCMD 和 OCG 一样,具有开/关状态,并且可以像 OCG 一样使用。与 OCG 不同的是,OCMD 的状态是通过评估一个或多个 OCG 的状态,使用特殊的布尔表达式来决定的。如果表达式结果为真,则 OCMD 的状态为 ON,否则为 OFF。
有两种方法来制定 OCMD 的可见性:
1. 使用 ocgs 和 policy 的组合:政策值的含义如下:
1)AnyOn –(默认)如果至少有一个 OCG 是 ON,则为 true。
2)AnyOff – 如果至少有一个 OCG 是 OFF,则为 true。
3)AllOn – 如果所有 OCG 都是 ON,则为 true。
4)AllOff – 如果所有 OCG 都是 OFF,则为 true。
假设你希望两个 PDF 对象同时显示,且在一个对象是 ON 时,另一个必须是 OFF: 解决方案:为对象 1 使用一个 OCG,为对象 2 使用 OCMD。创建 OCMD,使用set_ocmd(ocgs=[xref], policy="AllOff")
,并将 OCG 的 xref 提供给 OCMD。
2. 使用可见性表达式(ve):这是一个包含两个或更多项的列表。第一项是逻辑关键词:可以是“and”
、“or”
或“not”
。第二项及其后的项必须是整数或另一个列表。整数应为 OCG 的 xref。列表必须符合先前的规则。
示例:
1)set_ocmd(ve=["or", 4, ["not", 5], ["and", 6, 7]])
。这表示当下列条件为真时,OCMD 为 ON:4 是 ON,或者 5 是 OFF,或者 6 和 7 都是 ON
。
2)set_ocmd(ve=["not", xref])
。这与使用 ocgs 和 policy 创建 OCMD 时的效果相同。
有关详细信息和示例,请参见 Adobe PDF 参考手册第 224 页。还可以查看 此处的示例脚本。
可见性表达式(/VE)是 PDF 规范 1.6 版本的一部分,因此并非所有 PDF 查看器/阅读器都已支持此功能。因此,在这些查看器中可能会以标准方式进行处理。
新增于 v1.18.4
检索 OCMD 的定义。
参数:
返回类型:
dict
:返回一个字典,包含 xref
、ocgs
、policy
和 ve
键。新增于 v1.18.3
列出指定配置中的可选内容组及其状态。这是一个字典,包含在数组 /ON
、/OFF
或某些单选按钮组(/RBGroups
)中的 OCG 的 xref 列表。
参数:
示例:
>>> pprint(doc.get_layer())
{'off': [8, 9, 10], 'on': [5, 6, 7], 'rbgroups': [[7, 10]]}
>>>
新增于 v1.18.3,v1.22.5 中更新:支持锁定 OCG 的列表
批量更改可选内容组的状态。永久设置 OCG 的状态。
参数:
basestate="ON"
,则必须指定此项。basestate="OFF"
,则必须指定此项。on
或 off
中提及的 OCG 的状态。可能的值有 “ON”、“OFF” 或 “Unchanged”。支持大小写。示例:
>>> doc.set_layer(-1, basestate="OFF") # only changes the base state
>>> pprint(doc.get_layer())
{'basestate': 'OFF', 'off': [8, 9, 10], 'on': [5, 6, 7], 'rbgroups': [[7, 10]]}
新增于 v1.18.3
返回所有可选内容组的详细信息。这是一个字典,字典的键为 OCG 的 xref,值为另一个字典,包含相关的 OCG 信息。
示例:
>>> pprint(doc.get_ocgs())
{13: {'on': True,
'intent': ['View', 'Design'],
'name': 'Circle',
'usage': 'Artwork'},
14: {'on': True,
'intent': ['View', 'Design'],
'name': 'Square',
'usage': 'Artwork'},
15: {'on': False, 'intent': ['View'], 'name': 'Square', 'usage': 'Artwork'}}
>>>
新增于 v1.18.3
显示可以通过用户界面修改的可选内容的可见性状态。仅报告当前所选配置层中的项目。
返回的是一个包含字典的列表,每个字典表示一个项目的可见性信息。
字典字段含义:
/Order
数组中的嵌套级别。true
。新增于 v1.18.3
修改可选内容组的可见性状态。此方法类似于一些 PDF 查看器提供的用户界面功能。
参数:
Document.layer_configs()
中的序列号,或这些项目的“text”。解密文档
使用提供的密码解密文档。如果成功,文档数据可以访问。对于 PDF 文档,"所有者"(owner)和"用户"(user)具有不同的权限,因此可能存在不同的密码来授权这两种角色。该方法会自动为提供的密码建立适当的访问权限(无论是所有者权限还是用户权限)。
参数:
返回类型:
int
:如果成功,返回一个正值;否则返回零(表示密码与任何密码都不匹配)。如果返回值为正,则 Document.is_encrypted
设置为 False
。正值的返回码包含以下信息:
注意:文档可能只有所有者密码,而没有用户密码。通过doc.authenticate("") == 2
可以检测到这种情况。这允许在不进行身份验证的情况下打开并读取文档,但根据Document.permissions
的值,其他操作可能会受到限制。与任何 PDF 查看器不同,PyMuPDF(像 MuPDF 一样)在这种情况下会忽略这些限制。因此,你可以提取文本或添加/修改内容,即使相关的权限标志如PDF_PERM_COPY
、PDF_PERM_MODIFY
、PDF_PERM_ANNOTATE
等已关闭!构建符合法律合规要求的应用程序,仍然是你的责任。
新增于 v1.18.6
仅限 PDF:返回具有指定标签的页面编号——请注意,标签在 PDF 中可能不是唯一的。这意味着要对所有页面编号进行顺序搜索,以比较它们的标签。
注意:实现细节:此方法不会加载页面。
参数:
返回类型:
list
:返回一个包含所有具有此标签的页面编号的列表。如果未找到,返回空列表。新增于 v1.18.7
仅限 PDF:提取页面标签定义的列表。通常在通过 Document.set_page_labels()
传入之前进行修改。
返回类型:
list
:返回一个字典列表,每个字典定义了页面标签的设置。新增于 v1.18.6
仅限 PDF:添加或更新 PDF 的页面标签定义。
参数:
{'startpage': int, 'prefix': str, 'style': str, 'firstpagenum': int}
字典项说明:
示例:
[{'startpage': 6, 'prefix': 'A-', 'style': 'D', 'firstpagenum': 10},
{'startpage': 10, 'prefix': '', 'style': 'D', 'firstpagenum': 1}]
这将生成标签 “A-10”、 “A-11”、 “A-12”、 “A-13”、 “1”、 “2”、 “3”…,适用于第 6 页及之后的页面。第 0 至 5 页将没有标签(标签为空)。
新增于 v1.17.3
在可重新布局的文档中返回一个页面指针。在重新布局文档后,可以使用此方法的结果来查找页面的新位置。
注意:
参数:
(chapter, pno)
。返回类型:
pointer
:返回一个长整型指针。该指针用于在重新布局文档后查找页面的新位置。请勿修改或重新分配。新增于 v1.17.3
返回重新布局文档后页面的新位置。
参数:
Document.make_bookmark()
创建的指针。返回类型:
tuple
:返回新位置的 (chapter, pno)
。将当前文档转换为PDF并写入内存。所有文档类型都支持。参数与insert_pdf()
相同。本质上,您可以限制转换的页面子集、指定页面旋转以及调整页面顺序。
返回类型: bytes
返回: 一个Python字节对象,包含PDF文件图像。它是通过内部使用tobytes(garbage=4, deflate=True)
创建的。您可以直接将其输出到磁盘或将其作为PDF打开。以下是一些示例:
# 将XPS文件转换为PDF
xps = pymupdf.open("some.xps")
pdfbytes = xps.convert_to_pdf()
# 可以这样做 -->
pdf = pymupdf.open("pdf", pdfbytes)
pdf.save("some.pdf")
# 或者这样 -->
pdfout = open("some.pdf", "wb")
pdfout.tobytes(pdfbytes)
pdfout.close()
# 将图像文件复制到PDF页面
# 每个页面将具有图像的尺寸
doc = pymupdf.open() # 新PDF文档
imglist = [ ... image file names ...] # 例如图像文件目录
for img in imglist:
imgdoc = pymupdf.open(img) # 打开图像作为文档
pdfbytes = imgdoc.convert_to_pdf() # 将其转换为1页PDF
imgpdf = pymupdf.open("pdf", pdfbytes)
doc.insert_pdf(imgpdf) # 插入图像PDF
doc.save("allmyimages.pdf")
注意:该方法使用与mutool convert
命令行相同的逻辑。在大多数情况下,它效果很好,但请注意以下限制:
1)图像文件: 完美,没有检测到问题。然而,图像的透明度会被忽略。如果您需要透明度(如水印),请使用Page.insert_image()
方法。否则,建议使用此方法,因为它具有更好的性能。
2)XPS: 外观非常好。链接正常工作,但书签(大纲)丢失,可以很容易恢复。
3)EPUB、CBZ、FB2: 与XPS类似。
4)SVG: 效果一般。大致与svglib
类似。
get_toc(simple=True)
创建一个文档的目录(TOC),从文档的大纲链中提取内容。
参数:
simple
(bool
):指示是需要简单版还是详细版的目录。如果为 False
,列表中的每一项都会包含一个字典,其中包括每个大纲项的 linkDest
详情。返回类型:
list
返回值:
[lvl, title, page, dest]
,每个项的含义如下:
lvl
– 层级(正整数)。第一个条目总是 1。每一行的条目要么相等,要么递增 1,要么减少。title
– 标题(字符串)page
– 基于 1 的源页面编号(整数)。如果没有目标或超出文档范围,则为 -1。dest
– (仅当 simple=False
时包含)包含目录项的详情。包括以下内容:
kind
:目标类型,参见链接目标类型。file
:如果 kind
为 LINK_GOTOR
或 LINK_LAUNCH
,则为文件名。page
:目标页面,0 为基础,适用于 LINK_GOTOR
或 LINK_GOTO
。to
:目标页面上的位置(点)。zoom
:目标页面的缩放因子。xref
:项的 xref,如果没有 PDF,则为 0。color
:项目的颜色(PDF 中的 RGB 格式:红色、绿色、蓝色),如果没有 PDF,则省略。bold
:如果是粗体项文本,则为 true
,如果没有则省略(仅限 PDF)。italic
:如果是斜体项文本,则为 true
,如果没有则省略(仅限 PDF)。collapse
:如果子项被折叠,则为 true
,如果没有则省略(仅限 PDF)。nameddest
:目标名称,如果 kind=4
(PDF 仅限)。 (新功能,版本 1.23.7)xref_get_keys(xref)
(新增于 v1.18.7)
仅限 PDF:返回由其 xref 编号提供的 PDF 字典对象的字典键。
参数:
xref
(int
):xref 编号(在 v1.18.10 中发生了变化)。使用 -1
来访问特殊字典“PDF trailer”。返回类型:
tuple
返回值:
>>> from pprint import pprint
>>> import pymupdf
>>> doc=pymupdf.open("pymupdf.pdf")
>>> xref = doc.page_xref(0) # xref of page 0
>>> pprint(doc.xref_get_keys(xref)) # primary level keys of a page
('Type', 'Contents', 'Resources', 'MediaBox', 'Parent')
>>> pprint(doc.xref_get_keys(-1)) # primary level keys of the trailer
('Type', 'Index', 'Size', 'W', 'Root', 'Info', 'ID', 'Length', 'Filter')
>>>
xref_get_key(xref, key)
(新增于 v1.18.7)
仅限 PDF:返回给定 xref 的 PDF 字典键的类型和值。
参数:
xref
(int
):xref 编号(在 v1.18.10 中发生了变化)。使用 -1
来访问特殊字典“PDF trailer”。key
(str
):所需的 PDF 键。必须完全匹配(区分大小写)Document.xref_get_keys()
中包含的键。返回类型:
tuple
返回值:
一个元组(类型,值),其中类型是以下之一:“xref”、“array”、“dict”、“int”、“float”、“null”、“bool”、“name”、“string”或“unknown”(后者不应出现)。无论“类型”是什么,键的值始终以字符串格式呈现——请参见以下示例——并且(几乎总是)忠实地反映了PDF中存储的内容。在大多数情况下,值字符串的格式也能提供关于键类型的线索:
示例:
>>> for key in doc.xref_get_keys(xref):
print(key, "=" , doc.xref_get_key(xref, key))
Type = ('name', '/Page')
Contents = ('xref', '1297 0 R')
Resources = ('xref', '1296 0 R')
MediaBox = ('array', '[0 0 612 792]')
Parent = ('xref', '1301 0 R')
>>> #
>>> # Now same thing for the PDF trailer.
>>> # It has no xref, so -1 must be used instead.
>>> #
>>> for key in doc.xref_get_keys(-1):
print(key, "=", doc.xref_get_key(-1, key))
Type = ('name', '/XRef')
Index = ('array', '[0 8802]')
Size = ('int', '8802')
W = ('array', '[1 3 1]')
Root = ('xref', '8799 0 R')
Info = ('xref', '8800 0 R')
ID = ('array', '[]')
Length = ('int', '21111')
Filter = ('name', '/FlateDecode')
>>>
xref_set_key(xref, key, value)
新增功能: 从v1.18.7开始,v1.18.13做了更新。
v1.19.4更新: 如果设置值为“null”,则“物理”地删除该键。
仅限PDF: 设置(添加、更新、删除)给定xref的PDF字典对象的键值。
注意:这是一个专家级函数:如果你不知道自己在做什么,可能会导致PDF(部分)变得无法使用。请参考Adobe PDF参考文档,了解对象规范格式(第18页)以及像页面对象这样的特殊字典类型的结构。
参数:
具体的规则说明:
None
,它会导致该键被忽略,但不一定被删除,删除操作会在保存时通过垃圾回收完成。v1.19.4更新:如果该键没有路径层次结构(即不包含斜杠“/”),那么它将被完全删除。如果不确定,强烈建议使用get_pdf_str()
函数! 该函数会自动生成正确的括号、转义符号以及整体格式。例如,它会像这样进行转换:
pymupdf.get_pdf_str("Pay in $ or €.")
''
pymupdf.get_pdf_str("Prices in EUR (USD also accepted). Areas are in m².")
'(Prices in EUR \\(USD also accepted\\). Areas are in m\\262.)'
get_page_pixmap(pno: int, *, matrix: matrix_like = Identity, dpi=None, colorspace: Colorspace = csRGB, clip: rect_like = None, alpha: bool = False, annots: bool = True)
从页面 pno
(基于 0 的页面编号)创建一个 Pixmap。
参数:
pno
(int
):页面编号,基于 0 的编号。返回类型:
Pixmap
get_page_xobjects(pno)
新增功能: 从v1.16.13开始,v1.18.11做了更新。
仅限PDF: 返回页面引用的所有XObject(非图像)列表。
参数:
page_count
)。返回类型:
Page.show_pdf_page()
会创建这种类型的对象。返回内容:
该列表中的每个项都有以下布局:
Page.transformation_matrix
相乘。更新: v1.18.11中,bbox现在格式化为Rect对象。
get_page_images(pno, full=False)
仅限PDF: 返回页面引用的所有图像(直接或间接)的列表。
参数:
page_count
)。返回类型:
每个字段的含义:
colorspace
的值,可能存在的备用颜色空间。full=True
时存在。 注意:通常,这不是实际显示的图像列表。此方法仅解析若干PDF对象以收集对嵌入图像的引用。它不会分析页面内容,其中所有实际的图像显示命令被定义。要获取这些信息,请使用 Page.get_image_info()
方法。同时,可以查看“ 结构化字典输出”部分的讨论。
get_page_fonts(pno, full=False)
仅限PDF: 返回页面引用的所有字体(直接或间接)的列表。
参数:
page_count
)。/XObject
引用的,则在此处找到其xref。返回类型:
字段含义:
/XObject
引用,则为该/XObject
的xref。仅在full=True
时返回。示例:
>>> pprint(doc.get_page_fonts(0, full=False))
[(12, 'ttf', 'TrueType', 'FNUUTH+Calibri-Bold', 'R8', ''),
(13, 'ttf', 'TrueType', 'DOKBTG+Calibri', 'R10', ''),
(14, 'ttf', 'TrueType', 'NOHSJV+Calibri-Light', 'R12', ''),
(15, 'ttf', 'TrueType', 'NZNDCL+CourierNewPSMT', 'R14', ''),
(16, 'ttf', 'Type0', 'MNCSJY+SymbolMT', 'R17', 'Identity-H'),
(17, 'cff', 'Type1', 'UAEUYH+Helvetica', 'R20', 'WinAnsiEncoding'),
(18, 'ttf', 'Type0', 'ECPLRU+Calibri', 'R23', 'Identity-H'),
(19, 'ttf', 'Type0', 'TONAYT+CourierNewPSMT', 'R27', 'Identity-H')]
注意:该列表没有重复条目:xref
、name
和referencer
的组合是唯一的。通常,这是一个包含该页面实际使用字体的超集。例如,PDF创建者可能指定了一个全局字体列表,而每个页面只使用其中的一部分。
get_page_text(pno, output='text', flags=3, textpage=None, sort=False)
提取页面的文本,给定其页面编号 pno
(从0开始)。调用 Page.get_text()
方法。
参数:
page_count
)。返回类型:
layout(rect=None, width=0, height=0, fontsize=11)
重新分页(“重新流式化”)文档,根据给定的页面尺寸和字体大小。这只会影响某些文档类型,如电子书和HTML文档。如果文档不支持此功能,则会被忽略。支持的文档会在属性 is_reflowable
中显示为 True
。
参数:
height
一起使用,作为 rect
的替代。width
一起使用,作为 rect
的替代。select(s)
仅限PDF: 保留文档中页面编号在列表中的页面。空的序列或超出范围的元素会导致 ValueError
。有关更多详细信息,请参阅本章节底部的备注。
参数:
注意:序列中的页面编号不需要唯一,且不需要按任何特定顺序排列。这使得该方法成为一个多功能工具,例如选择仅偶数页或仅奇数页,或满足其他某些条件等。从技术层面来看,该方法总是会创建一个新的页面树。当只处理少量页面时,使用copy_page()
、move_page()
或delete_page()
方法会更简单。实际上,当文档包含许多页面时,它们也会快得多——至少快一个数量级。
set_metadata(m)
仅限PDF: 设置或更新文档的元数据,m
是一个Python字典。
参数:
None
。如果使用空字典 {}
,则所有元数据将被清空并设置为字符串“none”。如果只想选择性地更改某些值,请修改 doc.metadata
的副本,并将其作为参数传递。可以指定任意的UTF-8编码的Unicode值。注意:
get_xml_metadata()
仅限PDF: 获取文档的XML元数据。
返回类型:
set_xml_metadata(xml)
仅限PDF: 设置或更新文档的XML元数据。
参数:
set_pagelayout(value)
新功能 v1.22.2
仅限PDF: 设置 /PageLayout
。
参数:
"SinglePage"
、"OneColumn"
、"TwoColumnLeft"
、"TwoColumnRight"
、"TwoPageLeft"
、"TwoPageRight"
。支持小写。set_pagemode(value)
新功能 v1.22.2
仅限PDF: 设置 /PageMode
。
参数:
"UseNone"
、"UseOutlines"
、"UseThumbs"
、"FullScreen"
、"UseOC"
、"UseAttachments"
。支持小写。set_markinfo(value)
新功能 v1.22.2
仅限PDF: 设置 /MarkInfo
的值。
参数:
{"Marked": False, "UserProperties": False, "Suspects": False}
。该字典包含有关使用标签PDF约定的信息。有关详细信息,请参阅PDF规格。set_toc(toc, collapse=1)
仅限PDF: 用提供的参数替换当前的完整大纲树(目录)。成功执行后,可以通过 Document.get_toc()
或 Document.outline
正常访问新的大纲树。与其他输出导向方法一样,只有在使用 save()
(支持增量保存)之后,修改才会成为永久性的。内部,该方法包括以下两个步骤。示例如下所示。
步骤 1 删除所有现有的书签。
步骤 2 根据 toc
中包含的条目创建新的目录。
参数:
get_toc()
的输出变体是可以接受的。如果要完全删除目录,指定空序列或 None
。每个条目必须是一个列表,格式如下:[lvl, title, page [, dest]]
get_toc(False)
输出的字典)来详细控制书签的属性,详细信息请参阅 Document.get_toc()
。1
仅显示层级 1,更高层级必须通过 PDF 查看器展开。如果要展开所有内容,可以指定一个较大的整数、0
或 None
。返回类型:
注意:
从 v1.23.8 版本开始,目标 ‘to’ 坐标应与 get_toc()
返回的坐标系相同(内部会通过 page.cropbox
和 page.rotation_matrix
进行转换)。因此,像 set_toc(get_toc())
现在会给出未更改的目标 ‘to’ 坐标。
outline_xref(idx)
v1.17.7 新增
仅限PDF: 返回大纲项的 xref。此方法主要用于内部用途。
参数:
Document.get_toc()
列表中的条目索引。返回:
del_toc_item(idx)
v1.17.7 新增
v1.18.14 变更: 不再删除条目的文本,而是将其显示为灰色。
仅限PDF: 删除此目录项。这是一个高效的方法,它禁用相应的条目,但保持整个目录结构完整。物理上,该条目仍然存在于目录树中,但会显示为灰色,并且不再指向任何目标。
这也意味着,当需要时,可以使用 Document.set_toc_item()
为该条目分配一个新的目标。
参数:
Document.get_toc()
列表中的条目索引。set_toc_item(idx, dest_dict=None, kind=None, pno=None, uri=None, title=None, to=None, filename=None, zoom=0)
v1.17.7 新增
v1.18.6 变更
仅限PDF: 更改由索引标识的目录项。可以更改条目的标题、目标、外观(颜色、加粗、斜体)或折叠子项,甚至完全删除该条目。
如果只需要对选定条目进行特定更改,并且希望避免替换整个目录,可以使用此方法。这在处理大型目录时特别有用。
参数:
Document.get_toc()
列表中条目的索引。doc.get_toc(False)
输出的最后一项条目的字典作为模板。当提供时,其他参数将被忽略——除非 title
被提供。LINK_NONE
,则所有其他参数将被忽略,且该目录项将被移除——相当于 Document.del_toc_item()
。如果是 None
,则只修改标题,忽略其他参数。其他值将使用后续参数创建新的目标字典。1 <= pno <= doc.page_count
范围内。对于 LINK_GOTO
类型必填。LINK_URI
类型必填。None
。LINK_GOTO
类型相关。如果未提供,将选择页面顶部附近的点。LINK_GOTOR
和 LINK_LAUNCH
类型必填。示例使用: 更改SWIG手册的目录以实现以下效果:
>>> import pymupdf
>>> doc=pymupdf.open("SWIGDocumentation.pdf")
>>> toc = doc.get_toc(False) # we need the detailed TOC
>>> # list of level 1 indices and their titles
>>> lvl1 = [(i, item[1]) for i, item in enumerate(toc) if item[0] == 1]
>>> for i, title in lvl1:
d = toc[i][3] # get the destination dict
d["collapse"] = True # collapse items underneath
if "Python" in title: # show the 'Python' chapter
d["color"] = (1, 0, 0) # in red,
d["bold"] = True # bold and
d["italic"] = True # italic
doc.set_toc_item(i, dest_dict=d) # update this toc item
>>> doc.save("NEWSWIG.pdf",garbage=3,deflate=True)
在上面的示例中,我们只更改了文件中 1240 个目录项中的 42 个。
bake(*, annots=True, widgets=True)
仅限PDF: 将注释和/或表单控件转换为页面的永久部分。此方法将修改PDF文档。如果 widgets
设置为 True
,文档将不再是“表单PDF”。
所有页面看起来将是一样的,但将不再包含注释或表单字段。可见的部分将根据需要转换为标准文本、矢量图形或图像。
此方法可以作为PDF到PDF转换的有效替代方法,使用 Document.convert_to_pdf()
。
请注意,注释是复杂的对象,可能包含超出其视觉外观的更多数据。例如,“文本”注释和“附件文件”注释。当使用此方法将注释/表单控件“嵌入”时,所有这些底层信息(附加文件、评论、相关的PopUp注释等)将会丢失,并在下一次垃圾回收时被删除。
例如,在 Page.show_pdf_page()
中(该方法不支持注释和表单控件)当源页面应在目标中完全相同显示时,可以使用此功能。
参数:
can_save_incrementally()
v1.16.0 新增
检查文档是否可以增量保存。使用此方法可以在选择正确选项时避免遇到异常。
scrub(attached_files=True, clean_pages=True, embedded_files=True, hidden_text=True, javascript=True, metadata=True, redactions=True, redact_images=0, remove_links=True, reset_fields=True, reset_responses=True, thumbnails=True, xml_metadata=True)
v1.16.14 新增
仅限PDF: 从PDF中移除潜在的敏感数据。此功能灵感来源于Adobe Acrobat产品中的类似“Sanitize”功能。该过程可以通过多个选项进行配置。
参数:
False
,则同时也会清除隐藏文本和删减部分。0
(忽略)、1
(覆盖重叠部分)或 2
(移除)。save(outfile, garbage=0, clean=False, deflate=False, deflate_images=False, deflate_fonts=False, incremental=False, ascii=False, expand=0, linear=False, pretty=False, no_new_id=False, encryption=PDF_ENCRYPT_NONE, permissions=-1, owner_pw=None, user_pw=None, use_objstms=0)
v1.18.7 变更
v1.19.0 变更
v1.24.1 变更
仅限PDF: 保存文档的当前状态。
参数:
open(...)
或 io.BytesIO()
创建。选择 io.BytesIO()
类似于 Document.tobytes()
,等同于内部创建的 io.BytesIO().getvalue()
输出。0
= 无操作1
= 移除未使用(未引用)对象2
= 除了1,还会压缩xref表3
= 除了2,还会合并重复对象4
= 除了3,还会检查流对象的重复。由于这些数据通常较大,因此可能会很慢。outfile
为字符串或 pathlib.Path
且等于 Document.name
时可使用。如果文件已解密或修复,并且在某些其他情况下,不能使用此选项。为确保此选项可用,请检查 Document.can_save_incrementally()
。如果返回 False
,则需要保存为新文件。0
= 无操作1
= 图像2
= 字体255
= 所有Document.xref_object()
的默认输出方式呈现。/ID
字段。如果文件本身没有此字段,也禁止创建新字段。默认值为 False
,因此每次保存将导致文件标识的更新。Document Permissions
了解可能的值。默认值为授予所有权限。deflate
参数的值,转换后的对象定义将被压缩,这可以显著减少文件大小。警告:该方法不会检查是否已经存在该名称的文件,因此不会要求确认,直接覆盖文件。作为开发者,你需要自行处理文件覆盖的逻辑。
注意:
garbage=3|4
, deflate=True
, use_objstms=True|1
等保存选项。不要更改默认值 expand=False|0
, clean=False|0
, incremental=False|0
, linear=False|0
。这是“无损”的文件大小压缩。也有一个便捷的版本 Document.ez_save()
,默认设置了这些值,请参见下面的说明。ez_save(*args, **kwargs)
新增于 v1.18.11
仅限PDF:与 Document.save()
相同,但默认设置已更改:deflate=True
, garbage=3
, use_objstms=1
。
saveIncr()
仅限PDF:增量保存文档。这是 doc.save(doc.name, incremental=True, encryption=PDF_ENCRYPT_KEEP)
的便捷缩写。
注意:如果文档包含已验证的签名,保存时可能需要使用增量保存,否则保存为新文件会使签名失效。
tobytes(garbage=0, clean=False, deflate=False, deflate_images=False, deflate_fonts=False, ascii=False, expand=0, linear=False, pretty=False, no_new_id=False, encryption=PDF_ENCRYPT_NONE, permissions=-1, owner_pw=None, user_pw=None, use_objstms=0)
更新于 v1.18.7
更新于 v1.19.0
更新于 v1.24.1
仅限PDF:将文档的当前内容写入字节对象,而不是写入文件。显然,需要注意内存要求。各参数的含义与 save()
相同。章节FAQ中有一个使用此方法作为 pdfrw
预处理器的示例。
(更新于 v1.16.0) 增强的加密支持。
返回类型:bytes
返回:包含完整文档的字节对象。
search_page_for(pno, text, quads=False)
搜索页号为 pno
的页面上的“text”。与对应的 Page.search_for()
完全相同。任何整数 -∞ < pno < page_count
都是有效的。
insert_pdf(docsrc, from_page=-1, to_page=-1, start_at=-1, rotate=-1, links=True, annots=True, widgets=True, show_progress=0, final=1)
仅限PDF:复制 docsrc
PDF 文档中的页面范围 [from_page, to_page](包括两者)到当前文档。插入将从页面号 start_at
开始。-1
表示使用默认值。所有复制的页面将根据指定值旋转。可以排除链接、注释和小部件,详见下文。所有页码都是基于0的。
参数:
docsrc (Document)
– 一个已打开的PDF文档,不能是当前文档。它可能与同一文件相关。from_page (int)
– docsrc
中的第一页,默认为零。to_page (int)
– 要复制的 docsrc
中的最后一页,默认是最后一页。start_at (int)
– 复制的第一页面,将成为目标文档中的 start_at
页面。默认为-1,将页面范围附加到末尾。如果是0,则在当前第一页之前插入页面范围。rotate (int)
– 所有复制的页面将按指定的值(以度为单位,90的整数倍)进行旋转。links (bool)
– 是否包括链接(内部和外部)在复制中。默认为 True
。始终排除命名链接(LINK_NAMED)和指向复制页面范围外部的内部链接。annots (bool)
– 是否包括注释在复制中。widgets (bool)
– 是否包括小部件(表单字段)在复制中。如果为 True
且源页面包含表单字段,则目标PDF将转换为表单PDF(如果还不是的话)。show_progress (int)
– 新于 v1.17.7,指定大于零的间隔大小,以便在 sys.stdout
上查看进度消息。每次间隔后,将打印类似“已插入 30 个页面中的 47 个”的消息。final (int)
– 新于 v1.18.0,控制是否在此方法调用后丢弃已复制对象的列表,默认为 True
。对于从同一源PDF中进行的多个插入,除最后一个外应设置为 0。这可以显著节省目标文件的大小并加快执行速度。注意:
这是一个基于页面的方法。因此,源文档的文档级信息通常会被忽略。示例包括可选内容、嵌入文件、结构元素、目录、页面标签、元数据、命名目标(及其他命名条目)等。
如果 from_page > to_page
,页面将按反向顺序复制。如果 0 <= from_page == to_page
,则只会复制一页。
docsrc
的目录条目不会被复制。不过,可以轻松恢复结果文档的目录。可以查看下面的示例和 examples
目录中的程序 join.py
,它可以连接PDF文档并同时将相应部分的目录合并。
insert_file(infile, from_page=-1, to_page=-1, start_at=-1, rotate=-1, links=True, annots=True, show_progress=0, final=1)
新于 v1.22.0
仅限PDF:将任意支持的文档添加到当前PDF。打开 “infile” 作为文档,将其转换为PDF,然后调用 Document.insert_pdf()
。参数与该方法相同。此方法提供了一种简便的方式将图像作为完整页面添加到输出PDF中。
参数:
infile (multiple)
– 要插入的输入文档。可以是有效文件名的规范,也可以是PixMap。new_page(pno=-1, width=595, height=842)
仅限PDF:插入一个空白页面。
参数:
pno (int)
– 新页面应插入的位置页码。必须满足 1 < pno <= page_count
。特殊值 -1
和 doc.page_count
表示插入到最后一页之后。width (float)
– 页面宽度。height (float)
– 页面高度。返回类型:Page
返回:返回创建的页面对象。
insert_page(pno, text=None, fontsize=11, width=595, height=842, fontname='helv', fontfile=None, color=None)
仅限PDF:插入一个新页面并添加一些文本。这个便捷函数结合了 Document.new_page()
和 Page.insert_text()
的部分功能。
参数:
pno (int)
– 新页面插入的位置(基于0的页码)。必须在 (-1, doc.page_count + 1)
范围内。特殊值 -1
和 doc.page_count
表示插入到最后一页之后。返回类型:int
返回:返回 Page.insert_text()
的结果(成功插入的行数)。
delete_page(pno=-1)
仅限PDF:删除指定页码的页面,页码范围为 -∞ < pno < page_count - 1
。
更新于 v1.18.14: 支持 Python 的 del
语句。
参数:
pno (int)
– 要删除的页面。负数表示从文档末尾倒数。例如,-1
表示最后一页。默认是最后一页。delete_pages(*args, **kwds)
更新于 v1.18.13: 增强了删除页面的灵活性。
更新于 v1.18.14: 支持 Python 的 del
语句。
**仅限PDF:**删除多个页面,页面号为基于0的数字。
格式 1:使用关键字。代表旧格式。删除连续范围的页面。
from_page
:要删除的第一页,若省略默认为0。to_page
:要删除的最后一页,若省略默认为文档中的最后一页。to_page
必须不小于 from_page
。格式 2:两个页码作为位置参数,处理方式如格式 1。
格式 3:一个位置参数作为整数,相当于 Page.delete_page()
。
格式 4:一个位置参数为列表、元组或 range()
类型的页面号。该序列的项目可以是任意顺序并且可以包含重复项。
格式 5:(新于 v1.18.14)现在可以使用 Python 的 del
语句和索引/切片表示法。
注意:(更新于 v1.14.17,优化于 v1.17.7) 为了保持有效的PDF结构,delete_page()
和此方法也会禁用指向已删除页面的目录项(书签)。这里的“禁用”意味着书签将指向无处,且在支持的PDF查看器中标题会显示为灰色。整体目录结构保持不变。它还会删除指向已删除页面的其他页面上的链接。对于页面数较多的文档,这可能需要较长的时间来响应。以下所有示例都将删除页面 500 到 519:
doc.delete_pages(500,
519)
doc.delete_pages(from_page=500,
to_page=519)
doc.delete_pages((500,
501,
502,
...
,
519))
doc.delete_pages(range(500,
520))
del
doc[500:520]
del
doc[(500,
501,
502,
...
,
519)]
del
doc[range(500,
520)]
通常,执行此方法的性能取决于剩余页面的数量,而非已删除页面的数量:例如,如果删除所有页面,剩下20页,所需的时间会大大减少。
copy_page(pno, to=-1)
仅限PDF: 在文档内复制一个页面引用。
参数:
pno (int)
– 要复制的页面。必须在 0 <= pno < page_count
范围内。to (int)
– 要插入复制页面的位置页码。默认值是插入到最后一页之后。注意:
此方法仅创建页面对象的一个新引用,而不是一个新的页面对象。所有复制的页面将具有相同的属性值,包括 Page.xref
。这意味着对其中一个副本的任何更改将出现在所有副本中。
fullcopy_page(pno, to=-1)
新功能于 v1.14.17:
仅限PDF: 完全复制(重复)一个页面。
参数:
pno (int)
– 要复制的页面。必须在 0 <= pno < page_count
范围内。to (int)
– 要插入复制页面的位置页码。默认值是插入到最后一页之后。注意:
与 copy_page()
不同,此方法创建一个新的页面对象(具有新的 xref
),可以独立于原始页面进行更改。
任何弹出窗口和“IRT”(响应)注释都不会被复制,以避免可能的错误情况。
move_page(pno, to=-1)
仅限PDF: 在文档内移动(复制并删除原始页面)一个页面。
参数:
pno (int)
– 要移动的页面。必须在 0 <= pno < page_count
范围内。to (int)
– 要插入移动页面的位置页码。默认值是将页面移动到最后一页之后。need_appearances(value=None)
新功能于 v1.17.4:
仅限PDF: 获取或设置表单PDF的 /NeedAppearances
属性。
引用:“(可选)一个标志,指定是否为文档中的所有小部件注释构建外观流和外观字典… 默认值:false。” 这有助于控制某些阅读器/查看器的行为。
参数:
value (bool)
– 设置该属性的值。如果省略或为 None
,则查询当前值。返回类型:bool
返回:
None
:不是表单PDF,或属性未定义。True / False
:该属性的值(无论是刚设置还是已有值)。如果没有表单PDF,则无效。get_sigflags()
仅限PDF: 返回文档是否包含签名字段。这是一个可选的PDF属性:如果不存在(返回值为 -1
),则无法得出结论—PDF创建者可能根本没有使用它。
返回类型:int
返回:
-1
:不是表单PDF / 没有记录签名字段 / 未找到 SigFlags
。1
:至少存在一个签名字段。3
:包含的签名可能会被作废,如果文件以某种方式保存(写入),改变了它之前的内容,而不是增量更新。embfile_add(name, buffer, filename=None, ufilename=None, desc=None)
更新于 v1.14.16: 参数顺序已更改,以符合其他函数的调用模式。
仅限PDF: 嵌入一个新文件。所有字符串参数,除了名称外,均可为 Unicode(在早期版本中,只有 ASCII 正确工作)。文件内容将被压缩(在有利的情况下)。
参数:
name (str)
– 条目标识符,不能为空且不得与现有名称冲突。buffer (bytes, bytearray, BytesIO)
– 文件内容。io.BytesIO
。filename (str)
– 可选文件名,仅用于文档,如果为 None
,则设置为 name
。ufilename (str)
– 可选Unicode文件名,仅用于文档,如果为 None
,则设置为 filename
。desc (str)
– 可选描述,仅用于文档,如果为 None
,则设置为 name
。返回类型:int
返回:
xref
。此外,文件对象将自动获得PDF的 /CreationDate
和 /ModDate
键,基于当前的日期时间。embfile_count()
更新于 v1.14.16: 现在是一个方法,在早期版本中是一个属性。
仅限PDF: 返回嵌入文件的数量。
embfile_get(item)
仅限PDF: 根据条目号或名称检索嵌入文件的内容。如果文档不是PDF,或无法找到该条目,将引发异常。
参数:
item (int, str)
– 条目的索引或名称。整数必须在 embfile_count()
范围内。返回类型:bytes
embfile_del(item)
更新于 v1.14.16: 现在可以通过索引删除条目。
仅限PDF: 从 /EmbeddedFiles
中移除条目。正如往常一样,嵌入的文件内容的物理删除(以及文件空间的回收)仅会在文档保存为新文件并使用适当的垃圾回收选项时发生。
参数:
item (int/str)
– 条目的索引或名称。警告:
当指定条目名称时,此函数仅删除第一个具有该名称的条目。请注意,非PyMuPDF创建的PDF可能包含重复的名称。因此,您可能需要采取适当的预防措施。
embfile_info(item)
更新于 v1.18.13:
仅限PDF: 检索给定条目的嵌入文件信息,可以通过条目号或名称来检索。
参数:
item (int/str)
– 条目的索引或名称。整数必须在 embfile_count()
范围内。返回类型:dict
返回:一个字典,包含以下键:
name
– (str) 该条目存储的名称filename
– (str) 文件名ufilename
– (unicode) 文件名description
– (str) 描述size
– (int) 原始文件大小length
– (int) 压缩后的文件长度creationDate
– (str) 项目创建日期时间,以PDF格式表示modDate
– (str) 最后修改日期时间,以PDF格式表示collection
– (int) 关联的PDF投资组合项目的xref,如果没有,则为零checksum
– (str) 存储文件内容的哈希值,作为十六进制字符串。根据PDF规范,应该是MD5,但也可能使用其他哈希算法。embfile_names()
仅限PDF: 返回嵌入文件名称的列表。名称的顺序与文档中物理顺序相同。
返回类型:list
embfile_upd(item, buffer=None, filename=None, ufilename=None, desc=None)
仅限PDF: 更改嵌入文件,根据其条目号或名称。所有参数都是可选的,默认值会导致无操作。
参数:
item (int/str)
– 条目的索引或名称。整数必须在 embfile_count()
范围内。buffer (bytes, bytearray, BytesIO)
– 新的文件内容。io.BytesIO
。filename (str)
– 新的文件名。ufilename (str)
– 新的Unicode文件名。desc (str)
– 新的描述。更新于 v1.18.13: 此方法现在返回文件对象的 xref
。
返回类型:int
返回:文件对象的 xref
。同时,自动将其 /ModDate
PDF键更新为当前的日期时间。
close()
释放与文档关联的对象和空间分配。如果是从文件创建的,也会关闭文件名(将控制权交给操作系统)。显式关闭文档相当于删除文档,del doc
或将其赋值为其他内容,例如 doc = None
。
xref_object(xref, compressed=False, ascii=False)
新功能于 v1.16.8
更新于 v1.18.10
仅限PDF: 返回PDF对象的定义源。
参数:
xref (int)
– 对象的xref。更新于 v1.18.10: 传入 -1 时返回PDF trailer源。compressed (bool)
– 是否生成不带换行符或空格的紧凑输出。ascii (bool)
– 是否对二进制数据进行ASCII编码。返回类型:str
返回:对象的定义源。
pdf_catalog()
新功能于 v1.16.8
仅限PDF: 返回PDF目录(或根)对象的xref编号。使用此编号与 Document.xref_object()
一起查看其源。
pdf_trailer(compressed=False)
新功能于 v1.16.8
仅限PDF: 返回PDF的trailer源,通常位于PDF文件的末尾。这相当于使用 Document.xref_object()
并传入xref参数为 -1。
xref_stream(xref)
新功能于 v1.16.8
仅限PDF: 返回xref流对象的解压内容。
参数:
xref (int)
– xref编号。返回类型:bytes
返回:该对象的(解压缩)流。
xref_stream_raw(xref)
新功能于 v1.16.8
仅限PDF: 返回未修改的(特别是未解压缩的)xref流对象内容。否则与 Document.xref_stream()
相同。
返回类型:bytes
返回:该对象的(原始,未修改的)流。
update_object(xref, obj_str, page=None)
新功能于 v1.16.8
仅限PDF: 用提供的字符串替换xref对象的定义。如果xref是新的,则此指令完成对象定义。如果还提供了页面对象,它的链接和注释将在之后重新加载。
参数:
xref (int)
– xref编号。obj_str (str)
– 包含有效PDF对象定义的字符串。page (Page)
– 页面对象。如果提供,表示该页面的注释应在反映链接和/或注释变化后刷新(重新加载)。返回类型:int
返回:如果成功返回零,否则将引发异常。
update_stream(xref, data, new=False, compress=True)
新功能于 v1.16.8
更新于 v1.19.2: 新增了“compress”参数
更新于 v1.19.6: 弃用了“new”参数。现在确认对象是PDF字典对象。
仅限PDF: 替换由xref标识的对象的流,如果该对象不是流,则将其转化为流。此功能会在有益的情况下自动执行压缩操作(“deflate”)。
参数:
xref (int)
– xref编号。stream (bytes|bytearray|BytesIO)
– 流的新内容。io.BytesIO
对象。)new (bool)
– 已弃用并被忽略。在 v1.20.0 后将被移除。compress (bool)
– 是否压缩插入的流。如果为 True
(默认值),流将使用 /FlateDecode
压缩(如果有益),否则流将按原样插入。引发:
ValueError
– 如果xref不是PDF字典对象,则会引发此异常。空字典 <<>>
被接受。所以如果您刚创建了xref并想给它插入流,首先执行 doc.update_object(xref, "<<>>")
,然后使用此方法插入流数据。此方法主要(但不完全是)用于操作包含PDF操作符语法的流(例如页内容流)。
示例:假设您不再希望页面上显示某个图像。可以通过删除其内容源中的相关引用来实现——图像将在重新加载页面后消失。但页面的资源对象仍会显示该图像作为页面的引用。此时,可以使用 save
参数 clean=True
来确保PDF操作符源和对象结构的一致性。
xref_copy(source, target, *, keep=None)
新功能于 v1.19.5
仅限PDF: 将目标xref设置为源xref的精确副本。如果源是流数据,那么这些数据也会被复制。
参数:
source (int)
– 源xref。必须是现有的字典对象。target (int)
– 目标xref。必须是现有的字典对象。如果xref刚刚被创建,请确保将其初始化为具有最小规范 <<>>
的PDF字典。keep (list)
– 一个可选的顶级键列表,这些键在复制过程中不应从目标中移除。注意:
copy()
很相似。keep
列表中指定要排除的例外键。如果源中有同名的键,它的值仍会替换目标中的值。extract_image(xref)
仅限PDF: 提取文档中存储的图像数据和元信息。输出可以直接用来作为图像文件存储,或作为PIL、Pixmap创建的输入等。此方法尽量避免使用pixmaps来呈现图像,而是以图像的原始格式(例如JPEG)提供。
参数:
xref (int)
– 图像对象的xref。如果不在 range(1, doc.xref_length())
范围内,或者对象不是图像,或者发生其他错误,将返回 None
,并且不会抛出异常。返回类型:dict
返回:一个字典,包含以下键:
ext (str)
图像类型(例如 'jpeg'),可用作图像文件扩展名smask (int)
stencil(/SMask)图像的xref编号,或者为零width (int)
图像宽度height (int)
图像高度colorspace (int)
图像的颜色空间编号cs-name (str)
图像的颜色空间名称xres (int)
x方向的分辨率,请参见分辨率。yres (int)
y方向的分辨率,请参见分辨率。image (bytes)
图像数据,可作为图像文件内容使用例如:
>>> d = doc.extract_image(1373)
>>> d
{'ext': 'png', 'smask': 2934, 'width': 5, 'height': 629, 'colorspace': 3, 'xres': 96,
'yres': 96, 'cs-name': 'DeviceRGB',
'image': b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x05\ ...'}
>>> imgout = open(f"image.{d['ext']}", "wb")
>>> imgout.write(d["image"])
102
>>> imgout.close()
注意:
此方法与 pix = pymupdf.Pixmap(doc, xref)
然后调用 pix.tobytes()
存在功能重叠。主要区别在于:
extract_image
不总是提供PNG格式的图像;extract_image
通常比使用 Pixmap
快得多;None
(不抛出异常)。以下是相同PDF中的几个示例图像。
In [23]: %timeit pix = pymupdf.Pixmap(doc, 1268);pix.tobytes()
10.8 ms ± 52.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [24]: len(pix.tobytes())
Out[24]: 21462
In [25]: %timeit img = doc.extract_image(1268)
10.8 ms ± 86 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [26]: len(img["image"])
Out[26]: 21462
Document.extract_image()
的速度要快得多,且输出文件要小得多(2.48MB vs. 0.35MB):In [27]: %timeit pix = pymupdf.Pixmap(doc, 1186);pix.tobytes()
341 ms ± 2.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [28]: len(pix.tobytes())
Out[28]: 2599433
In [29]: %timeit img = doc.extract_image(1186)
15.7 µs ± 116 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [30]: len(img["image"])
Out[30]: 371177
新增于 v1.19.4:如果 named
为 True
,返回字典。
仅限 PDF:返回嵌入字体文件的数据和适当的文件扩展名。可以将此方法用于将字体存储为外部文件。该方法不会抛出异常(除非检查 PDF 和有效的 xref 时)。
参数:
xref
(int) – 要提取的字体的 PDF 对象编号。info_only
(bool) – 仅返回字体信息,不返回缓冲区。用于仅获取信息,避免分配大量缓冲区空间。named
(bool) – 如果为 True
,返回一个包含以下键的字典:name
(字体基本名称)、ext
(字体文件扩展名)、type
(字体类型)、content
(字体文件内容)。返回类型:
tuple, dict
返回值:
(basename, ext, type, content)
,其中 ext
是建议的 3 字节文件扩展名(字符串),basename
是字体的名称(字符串),type
是字体的类型(例如,“Type1”),content
是一个字节对象,包含字体文件的内容(或 b""
)。("", "", "", b"")
– 无效的 xref 或 xref 不是有效的字体对象。(basename, "n/a", "Type1", b"")
– 字体没有嵌入,因此无法提取。例如,PDF 基本 14 字体和 Type 3 字体。>>> # store font as an external file
>>> name, ext, _, content = doc.extract_font(4711)
>>> # assuming content is not None:
>>> ofile = open(name + "." + ext, "wb")
>>> ofile.write(content)
>>> ofile.close()
警告:
返回的 basename
在 PDF 中保持不变。因此,它可能包含某些字符(如空格),这可能不适合作为操作系统的文件名。请采取适当的措施。
注意:
返回的 basename
一般不是原始文件名,但它可能与原始文件名有一定相似性。
如果 named
为 True
,将返回包含以下键的字典:{'name': 'T1', 'ext': 'n/a', 'type': 'Type3', 'content': b''}
。
新增于 v1.16.8
仅限 PDF:返回文档的 XML 元数据的 xref。
新增于 v1.18.7
仅限 PDF:检查文档中是否存在链接或注释。
返回值:True / False
。与字段不同,链接和注释是存储在 PDF 文档的每个页面中的,因此只能通过解析每一页来检测。这些方法经过优化,可以高效地进行此操作,并在页面上找到时立即返回。如果文档包含成千上万的页面,但未找到链接或注释,可能会需要一些时间。
仅限 PDF:检查文档中字体的使用情况。如果字体是支持的,并且可以进行大小减小,则用一个只包含所用字符的版本替换该字体。
在保存文档之前立即使用此方法。
参数:
verbose
(bool) – 启用时,将各种进度信息写入 sysout
。这目前仅在 fallback
为 True
时有效。fallback
(bool) – 如果为 True
,使用已弃用的算法,该算法依赖于 fontTools
包(因此必须安装)。如果使用推荐的值 False
(默认值),则使用 MuPDF 的原生函数,这样速度更快并且可以子集化更多字体类型。不需要 fontTools
包。在创建新 PDF 时,使用像亚洲文字那样的较大字体时,可以显著减少嵌入字体的大小。使用 Story
类或 Page.insert_htmlbox()
方法时,多个字体可能会自动包含,而程序员对此并不知情。
在这些情况下,实际使用的字符集通常比字体中包含的字形数量要小得多。使用此方法可以将嵌入的字体二进制文件大小减少两个数量级——从几兆字节缩小到低两位千字节数。
创建字体子集会留下大量未使用的 PDF 对象(“幽灵”)。因此,请确保在保存文件时压缩并进行垃圾回收。建议使用 Document.ez_save()
。
新增于 v1.18.7
更改于 v1.18.9
更改于 v1.24.2,使用 MuPDF 的原生功能。
新增于 v1.19.0
仅限 PDF:启用日志记录。开始记录操作之前,使用此方法。
新增于 v1.19.0
仅限 PDF:开始记录一个由字符串 name
标识的“操作”。如果没有开始操作,日志记录的更新将失败。
新增于 v1.19.0
仅限 PDF:停止当前操作。从开始到结束的所有更新属于同一个操作单元,可以一起撤销/重做。
新增于 v1.19.0
仅限 PDF:返回当前操作的编号和总操作数。
返回一个元组 (step, steps)
,其中 step
是当前操作的编号,steps
是总操作数。如果 step
为 0,表示处于日志的顶部;如果 step
等于 steps
,则表示处于日志底部。任何非撤销或重做的更新都会删除当前操作之后的所有日志条目,新更新将成为日志中的最后一条条目,删除的操作将永久丢失。
新增于 v1.19.0
仅限 PDF:返回操作编号 step
的操作名称。
新增于 v1.19.0
仅限 PDF:查看是否可以从当前日志位置执行前进(“重做”)或后退(“撤销”)操作。
返回值是一个字典 {"undo": bool, "redo": bool}
。当其值为 True
时,可以执行相应的方法。
新增于 v1.19.0
仅限 PDF:撤销当前日志中的操作。此操作会向日志的顶部移动。
新增于 v1.19.0
仅限 PDF:重做当前日志中的操作。此操作会向日志的底部移动。
journal_save(filename)
新特性:v1.19.0
仅限PDF:将日志保存到文件中。
参数:
filename (str, fp)
– 文件名(字符串)或以“wb”模式打开的文件对象(或io.BytesIO()对象)。journal_load(filename)
新特性:v1.19.0
仅限PDF:从文件加载日志。启用文档的日志记录。如果日志已经启用,则会抛出异常。
参数:
filename (str, fp)
– 日志的文件名(字符串)或以“rb”模式打开的文件对象(或io.BytesIO()对象)。save_snapshot()
新特性:v1.19.0
仅限PDF:保存文档的“快照”。这是一个PDF文档,具有与日志记录兼容的特殊增量保存格式,因此没有可用的保存选项。对于新文档,不可能保存快照。
这是一个普通的PDF文档,完全没有使用限制。如果它没有被修改,可以与其日志一起使用以撤销/重做操作或继续更新。
outline
包含文档的第一个大纲条目(或None)。可以用作遍历所有大纲项的起点。如果访问加密且未通过验证的文档的此属性,将抛出AttributeError
。
类型:Outline
is_closed
如果文档仍然打开,则为False
。如果已关闭,则大多数其他属性和方法将被删除或禁用。此外,引用此文档的Page
对象(即使用Document.load_page()
创建的对象)及其相关对象将不再可用。出于参考目的,Document.name
仍然存在,并将包含原始文档的文件名(如果适用)。
类型:bool
is_dirty
如果这是一个PDF文档并包含未保存的更改,则为True
,否则为False
。
类型:bool
is_pdf
如果这是一个PDF文档,则为True
,否则为False
。
类型:bool
is_form_pdf
如果这不是PDF或没有表单字段,则为False
,否则返回根表单字段的数量(没有祖先的字段)。
(在v1.16.4中更改) 返回总的(根)表单字段数量。
类型:bool
,int
is_reflowable
如果文档具有可变的页面布局(如电子书或HTML),则为True
。在这种情况下,您可以在文档创建(打开)时或通过方法layout()
设置所需的页面尺寸。
类型:bool
is_repaired
新特性:v1.18.2
如果PDF在打开时已修复(因为存在重大结构问题),则为True
。对于非PDF文档,始终为False
。如果为True
,则在TOOLS.mupdf_warnings()
中存储了更多详细信息,并且Document.can_save_incrementally()
将返回False
。
类型:bool
is_fast_webaccess
新特性:v1.22.2
如果PDF是线性化格式,则为True
。对于非PDF文档,则为False
。
类型:bool
markinfo
新特性:v1.22.2
一个字典,表示/MarkInfo
值。如果未指定,返回空字典。如果不是PDF,则返回None
。
类型:dict
pagemode
新特性:v1.22.2
一个包含/PageMode
值的字符串。如果未指定,则返回默认值"UseNone"
。如果不是PDF,则返回None
。
类型:str
pagelayout
新特性:v1.22.2
一个包含/PageLayout
值的字符串。如果未指定,则返回默认值"SinglePage"
。如果不是PDF,则返回None
。
类型:str
version_count
新特性:v1.22.2
一个整数,计算文档中存在的版本数。如果不是PDF,则返回零,否则返回增量保存的次数加一。
类型:int
needs_pass
指示文档是否受密码保护,不能访问。如果为True
,即使文档已通过身份验证,该值也保持不变。为True
时,无法执行增量保存。
类型:bool
is_encrypted
此指示器最初等于Document.needs_pass
。成功验证后,它被设置为False
,以反映当前的情况。
类型:bool
permissions
在v1.16.0中更改:现在这是一个由位指示符组成的整数。之前是字典。
包含访问文档的权限。这是一个整数,包含相应位位置的布尔值。例如,如果doc.permissions & pymupdf.PDF_PERM_MODIFY > 0
,则表示您可以修改文档。有关详细信息,请参见Document Permissions
。
类型:int
metadata
包含文档的元数据,作为Python字典或None
(如果is_encrypted=True
且needPass=True
)。键包括format
、encryption
、title
、author
、subject
、keywords
、creator
、producer
、creationDate
、modDate
、trapped
。所有项的值为字符串或None
。
除了format
和encryption
,对于PDF文档,键名称与PDF中的/Creator
、/Producer
、/CreationDate
、/ModDate
、/Title
、/Author
、/Subject
、/Trapped
和/Keywords
有明显的对应关系。
format
包含文档格式(例如‘PDF-1.6’,‘XPS’,‘EPUB’)。
encryption
包含None
(无加密)或命名的加密方法(例如‘Standard V4 R4 128-bit RC4’)。请注意,即使needs_pass=False
,也可以指定加密方法。在这种情况下,可能没有授予所有权限。请检查Document.permissions
以了解详细信息。
如果日期字段包含有效数据(不一定是必须的!),它们以PDF特定的时间戳格式“D:
是12个字符的ISO时间戳(YYYYMMDDhhmmss),
是时区值(相对于GMT的时间间隔)。
类型:dict
name
包含创建Document
时使用的文件名或文件类型值。
类型:str
page_count
包含文档的页面数量。对于没有页面的文档,返回0。len(doc)
也会返回此结果。
类型:int
chapter_count
新特性:v1.17.0
包含文档中的章节数量。对于支持章节的文档(目前仅支持EPUB),始终至少为1。对于其他文档,返回1。
类型:int
last_location
新特性:v1.17.0
包含文档最后一页的位置(章节、页面编号)。对于支持章节的文档(目前仅支持EPUB),返回有效的章节和页面编号。如果没有页面,则返回(0, -1)
。
类型:int
FormFonts
一个包含在/AcroForm
对象中定义的表单字段字体名称的列表。如果不是PDF,则返回None
。
类型:list
注意:
对于更改PDF结构的方法(如insert_pdf()
、select()
、copy_page()
、delete_page()
等),请注意,程序中的对象或属性可能会失效或变成孤立对象。例如,Page
对象及其子对象(链接、注释、控件)、保存的旧页面计数、目录等。记得保持这些变量的更新或删除孤立对象。还请参考PyMuPDF中的确保一致性。
清除元数据。如果出于隐私/数据保护考虑执行此操作,请确保将文档保存为新文件,并且垃圾回收器参数大于0。这样,旧的/Info对象将被从文件中物理移除。在这种情况下,您可能还需要清除由多个PDF编辑器插入的XML元数据:
>>> import pymupdf
>>> doc=pymupdf.open("pymupdf.pdf")
>>> doc.metadata # look at what we currently have
{'producer': 'rst2pdf, reportlab', 'format': 'PDF 1.4', 'encryption': None, 'author':
'Jorj X. McKie', 'modDate': "D:20160611145816-04'00'", 'keywords': 'PDF, XPS, EPUB, CBZ',
'title': 'The PyMuPDF Documentation', 'creationDate': "D:20160611145816-04'00'",
'creator': 'sphinx', 'subject': 'PyMuPDF 1.9.1'}
>>> doc.set_metadata({}) # clear all fields
>>> doc.metadata # look again to show what happened
{'producer': 'none', 'format': 'PDF 1.4', 'encryption': None, 'author': 'none',
'modDate': 'none', 'keywords': 'none', 'title': 'none', 'creationDate': 'none',
'creator': 'none', 'subject': 'none'}
>>> doc.del_xml_metadata() # clear any XML metadata
>>> doc.save("anonymous.pdf", garbage = 4) # save anonymized doc
set_toc()
例子这展示了如何修改或添加目录。也可以查看 import.py 和 export.py 示例文件。
>>> import pymupdf
>>> doc = pymupdf.open("test.pdf")
>>> toc = doc.get_toc()
>>> for t in toc: print(t) # show what we have
[1, 'The PyMuPDF Documentation', 1]
[2, 'Introduction', 1]
[3, 'Note on the Name fitz', 1]
[3, 'License', 1]
>>> toc[1][1] += " modified by set_toc" # modify something
>>> doc.set_toc(toc) # replace outline tree
3 # number of bookmarks inserted
>>> for t in doc.get_toc(): print(t) # demonstrate it worked
[1, 'The PyMuPDF Documentation', 1]
[2, 'Introduction modified by set_toc', 1] # <<< this has changed
[3, 'Note on the Name fitz', 1]
[3, 'License', 1]
insert_pdf()
例子(1) 合并两个文档并包括它们的目录:
>>> doc1 = pymupdf.open("file1.pdf") # must be a PDF
>>> doc2 = pymupdf.open("file2.pdf") # must be a PDF
>>> pages1 = len(doc1) # save doc1's page count
>>> toc1 = doc1.get_toc(False) # save TOC 1
>>> toc2 = doc2.get_toc(False) # save TOC 2
>>> doc1.insert_pdf(doc2) # doc2 at end of doc1
>>> for t in toc2: # increase toc2 page numbers
t[2] += pages1 # by old len(doc1)
>>> doc1.set_toc(toc1 + toc2) # now result has total TOC
显然,可以在更一般的情况下找到类似的方法。只需确保层级不增加超过1即可。在toc2段之前和之后插入虚拟书签就能修复这种情况。还可以在示例目录中的 join.py 脚本中找到一个现成的GUI解决方案(wxPython)。
(2) 更多示例:
>>> # insert 5 pages of doc2, where its page 21 becomes page 15 in doc1
>>> doc1.insert_pdf(doc2, from_page=21, to_page=25, start_at=15)
>>> # same example, but pages are rotated and copied in reverse order
>>> doc1.insert_pdf(doc2, from_page=25, to_page=21, start_at=15, rotate=90)
>>> # put copied pages in front of doc1
>>> doc1.insert_pdf(doc2, from_page=21, to_page=25, start_at=0)
提取PDF中所有页面引用的图像并保存为单独的PNG文件:
for i in range(doc.page_count):
imglist = doc.get_page_images(i)
for img in imglist:
xref = img[0] # xref number
pix = pymupdf.Pixmap(doc, xref) # make pixmap from image
if pix.n - pix.alpha < 4: # can be saved as PNG
pix.save("p%s-%s.png" % (i, xref))
else: # CMYK: must convert first
pix0 = pymupdf.Pixmap(pymupdf.csRGB, pix)
pix0.save("p%s-%s.png" % (i, xref))
pix0 = None # free Pixmap resources
pix = None # free Pixmap resources
旋转PDF的所有页面:
>>> for page in doc: page.set_rotation(90)
本文详细介绍了PyMupdf中的Document类的各个方法和属性,便于Python调用参考。后续会继续介绍更多的类的详情和调用方法。