基础知识#
打开文件#
要打开一个文件,请执行以下操作:
import pymupdf
doc = pymupdf.open("a.pdf") # open a document
从 PDF 中提取文本#
要从 PDF 文件中提取所有文本,请执行以下操作:
import pymupdf
doc = pymupdf.open("a.pdf") # open a document
out = open("output.txt", "wb") # create a text output
for page in doc: # iterate the document pages
text = page.get_text().encode("utf8") # get plain text (is in UTF-8)
out.write(text) # write text of page
out.write(bytes((12,))) # write page delimiter (form feed 0x0C)
out.close()
当然,可以提取文本的不仅仅是 PDF - 所有支持的文档文件格式,例如 MOBI、EPUB、TXT 等,都可以提取文本。
注意
进一步了解
如果您的文档包含基于图片的文本内容,请在该页面上使用 OCR 进行后续文本提取
tp = page.get_textpage_ocr()
text = page.get_text(textpage=tp)
还有更多示例解释如何从特定区域提取文本或如何从文档中提取表格。请参阅文本操作指南。
您现在还可以以 Markdown 格式提取文本。
API 参考
从 PDF 中提取图片#
要从 PDF 文件中提取所有图片,请执行以下操作:
import pymupdf
doc = pymupdf.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 = pymupdf.Pixmap(doc, xref) # create a Pixmap
if pix.n - pix.alpha > 3: # CMYK: convert to RGB first
pix = pymupdf.Pixmap(pymupdf.csRGB, pix)
pix.save("page_%s-image_%s.png" % (page_index, image_index)) # save the image as png
pix = None
提取矢量图形#
要从文档页面中提取所有矢量图形,请执行以下操作:
doc = pymupdf.open("some.file")
page = doc[0]
paths = page.get_drawings()
这将返回一个字典,其中包含页面上找到的所有矢量绘图的路径。
合并 PDF 文件#
要合并 PDF 文件,请执行以下操作:
import pymupdf
doc_a = pymupdf.open("a.pdf") # open the 1st document
doc_b = pymupdf.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
合并 PDF 文件与其他类型的文件#
使用Document.insert_file()
,您可以调用此方法将支持的文件与 PDF 合并。例如:
import pymupdf
doc_a = pymupdf.open("a.pdf") # open the 1st document
doc_b = pymupdf.open("b.svg") # open the 2nd document
doc_a.insert_file(doc_b) # merge the docs
doc_a.save("a+b.pdf") # save the merged document with a new filename
注意
进一步了解
使用Document.insert_pdf()
和 Document.insert_file()
可以轻松合并 PDF。给定已打开的 PDF 文档,您可以将页面范围从一个复制到另一个。您可以选择放置复制页面的位置,反转页面顺序,并更改页面旋转。
GUI 脚本 join.py 使用此方法合并文件列表,同时合并相应的目录段。它看起来像这样:

API 参考
使用坐标#
在使用 PyMuPDF 时,有一个数学术语您应该感到熟悉 - “坐标”。请快速查看坐标部分,以了解坐标系,这将帮助您定位对象并理解文档空间。
向 PDF 添加水印#
要向 PDF 文件添加水印,请执行以下操作:
import pymupdf
doc = pymupdf.open("document.pdf") # open a document
for page_index in range(len(doc)): # iterate over pdf pages
page = doc[page_index] # get the page
# insert an image watermark from a file name to fit the page bounds
page.insert_image(page.bound(),filename="watermark.png", overlay=False)
doc.save("watermarked-document.pdf") # save the document with a new filename
注意
进一步了解
添加水印本质上就像在每个 PDF 页面底部添加图片一样简单。您应该确保图片具有所需的透明度和宽高比,以使其呈现您想要的效果。
在上面的示例中,每个文件引用都创建一个新图片,但为了获得更好的性能(节省内存和文件大小),此图片数据应仅引用一次 - 有关具体实现,请参阅Page.insert_image()
上的代码示例和解释。
API 参考
向 PDF 添加图片#
要向 PDF 文件添加图片(例如徽标),请执行以下操作:
import pymupdf
doc = pymupdf.open("document.pdf") # open a document
for page_index in range(len(doc)): # iterate over pdf pages
page = doc[page_index] # get the page
# insert an image logo from a file name at the top left of the document
page.insert_image(pymupdf.Rect(0,0,50,50),filename="my-logo.png")
doc.save("logo-document.pdf") # save the document with a new filename
旋转 PDF#
要向页面添加旋转,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open document
page = doc[0] # get the 1st page of the document
page.set_rotation(90) # rotate the page
doc.save("rotated-page-1.pdf")
裁剪 PDF#
要将页面裁剪到定义的Rect,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open document
page = doc[0] # get the 1st page of the document
page.set_cropbox(pymupdf.Rect(100, 100, 400, 400)) # set a cropbox for the page
doc.save("cropped-page-1.pdf")
附加文件#
要向页面附加另一个文件,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open main document
attachment = pymupdf.open("my-attachment.pdf") # open document you want to attach
page = doc[0] # get the 1st page of the document
point = pymupdf.Point(100, 100) # create the point where you want to add the attachment
attachment_data = attachment.tobytes() # get the document byte data as a buffer
# add the file annotation with the point, data and the file name
file_annotation = page.add_file_annot(point, attachment_data, "attachment.pdf")
doc.save("document-with-attachment.pdf") # save the document
注意
进一步了解
使用Page.add_file_annot()
添加文件时,请注意 filename
的第三个参数应包含实际文件扩展名。否则,附加的文件可能无法被识别为可打开的文件。例如,如果 filename
仅为“attachment”,则在查看生成的 PDF 并尝试打开附件时,您很可能会遇到错误。但是,如果使用“attachment.pdf”,PDF 阅读器可以将其识别并作为有效文件类型打开。
附件的默认图标是“图钉”,但是您可以通过设置 icon
参数来更改它。
API 参考
嵌入文件#
要向文档嵌入文件,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open main document
embedded_doc = pymupdf.open("my-embed.pdf") # open document you want to embed
embedded_data = embedded_doc.tobytes() # get the document byte data as a buffer
# embed with the file name and the data
doc.embfile_add("my-embedded_file.pdf", embedded_data)
doc.save("document-with-embed.pdf") # save the document
删除页面#
要从文档中删除页面,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open a document
doc.delete_page(0) # delete the 1st page of the document
doc.save("test-deleted-page-one.pdf") # save the document
要从文档中删除多个页面,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open a document
doc.delete_pages(from_page=9, to_page=14) # delete a page range from the document
doc.save("test-deleted-pages.pdf") # save the document
如果我删除书签或超链接引用的页面,会发生什么?#
书签(目录中的条目)将变为非活动状态,并且不再导航到任何页面。
超链接将从包含它的页面中移除。该页面上的可见内容不会以任何其他方式更改。
注意
进一步了解
页面索引是从零开始的,因此要删除文档的第 10 页,您可以执行以下操作 doc.delete_page(9)
。
类似地,doc.delete_pages(from_page=9, to_page=14)
将删除第 10 页到第 15 页(包括两端)。
API 参考
重新排列页面#
要更改页面的顺序(即重新排列页面),请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open a document
doc.move_page(1,0) # move the 2nd page of the document to the start of the document
doc.save("test-page-moved.pdf") # save the document
复制页面#
要复制页面,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open a document
doc.copy_page(0) # copy the 1st page and puts it at the end of the document
doc.save("test-page-copied.pdf") # save the document
选择页面#
要选择页面,请执行以下操作:
import pymupdf
doc = pymupdf.open("test.pdf") # open a document
doc.select([0, 1]) # select the 1st & 2nd page of the document
doc.save("just-page-one-and-two.pdf") # save the document
注意
进一步了解
使用 PyMuPDF,您可以复制、移动、删除或重新排列 PDF 的页面。存在直观的方法,使您可以按页面级别执行此操作,例如Document.copy_page()
方法。
或者,您也可以准备一个完整的全新页面布局,形式为一个 Python 序列,其中包含您想要的页码,按您想要的顺序排列,并且每页可以出现任意多次。以下示例可能说明使用Document.select()
可以做什么:
doc.select([1, 1, 1, 5, 4, 9, 9, 9, 0, 2, 2, 2])
现在,让我们准备一个用于双面打印的 PDF(在不支持直接双面打印的打印机上):
页面数量由 len(doc)
给出(等于 doc.page_count
)。以下列表分别代表偶数和奇数页码:
p_even = [p in range(doc.page_count) if p % 2 == 0]
p_odd = [p in range(doc.page_count) if p % 2 == 1]
此代码片段创建相应的子文档,然后可以用于打印文档
doc.select(p_even) # only the even pages left over
doc.save("even.pdf") # save the "even" PDF
doc.close() # recycle the file
doc = pymupdf.open(doc.name) # re-open
doc.select(p_odd) # and do the same with the odd pages
doc.save("odd.pdf")
欲了解更多信息,请参阅此 Wiki 文章。
以下示例将反转所有页面的顺序(非常快: 对于 Adobe PDF Reference 的 756 页文档,耗时不到一秒):
lastPage = doc.page_count - 1
for i in range(lastPage):
doc.move_page(lastPage, i) # move current last page to the front
此代码片段将 PDF 与自身复制一遍,这样它将包含页面 0, 1, …, n, 0, 1, …, n (非常快,文件大小没有明显增加!)
page_count = len(doc)
for i in range(page_count):
doc.copy_page(i) # copy this page to after last page
API 参考
添加空白页#
要添加空白页,请执行以下操作:
import pymupdf
doc = pymupdf.open(...) # some new or existing PDF document
page = doc.new_page(-1, # insertion point: end of document
width = 595, # page dimension: A4 portrait
height = 842)
doc.save("doc-with-new-blank-page.pdf") # save the document
注意
进一步了解
使用此方法创建具有其他预定义纸张格式的页面
w, h = pymupdf.paper_size("letter-l") # 'Letter' landscape
page = doc.new_page(width = w, height = h)
便捷函数paper_size()
知道 40 多种行业标准纸张格式供您选择。要查看它们,请检查字典 paperSizes
。将所需的字典键传递给paper_size()
以获取纸张尺寸。支持大小写。如果您在格式名称后附加“-L”,将返回横向版本。
这是一个 3 行代码,用于创建一个包含一个空白页面的 PDF 文件。其文件大小为 460 字节
doc = pymupdf.open()
doc.new_page()
doc.save("A4.pdf")
API 参考
paperSizes
插入包含文本内容的页面#
使用Document.insert_page()
方法也可以插入一个新页面,并接受相同的 width
和 height
参数。但它也允许您在新页面中插入任意文本,并返回插入的行数。
import pymupdf
doc = pymupdf.open(...) # some new or existing PDF document
n = doc.insert_page(-1, # default insertion point
text = "The quick brown fox jumped over the lazy dog",
fontsize = 11,
width = 595,
height = 842,
fontname = "Helvetica", # default font
fontfile = None, # any font file name
color = (0, 0, 0)) # text color (RGB)
注意
进一步了解
text 参数可以是一个(或多个)字符串(假定 UTF-8 编码)。插入将从Point (50, 72) 开始,即页面顶部下方一英寸、左侧 50 点的位置。返回插入的文本行数。
API 参考
拆分单页#
这涉及将 PDF 的页面任意拆分成多个部分。例如,您可能有一个包含 Letter 格式页面的 PDF,您想以四倍放大系数打印它:每页被拆分成 4 个部分,每个部分都将成为一个单独的 Letter 格式 PDF 页面。
import pymupdf
src = pymupdf.open("test.pdf")
doc = pymupdf.open() # empty output PDF
for spage in src: # for each page in input
r = spage.rect # input page rectangle
d = pymupdf.Rect(spage.cropbox_position, # CropBox displacement if not
spage.cropbox_position) # starting at (0, 0)
#--------------------------------------------------------------------------
# example: cut input page into 2 x 2 parts
#--------------------------------------------------------------------------
r1 = r / 2 # top left rect
r2 = r1 + (r1.width, 0, r1.width, 0) # top right rect
r3 = r1 + (0, r1.height, 0, r1.height) # bottom left rect
r4 = pymupdf.Rect(r1.br, r.br) # bottom right rect
rect_list = [r1, r2, r3, r4] # put them in a list
for rx in rect_list: # run thru rect list
rx += d # add the CropBox displacement
page = doc.new_page(-1, # new output page with rx dimensions
width = rx.width,
height = rx.height)
page.show_pdf_page(
page.rect, # fill all new page with the image
src, # input document
spage.number, # input page number
clip = rx, # which part to use of input page
)
# that's it, save output file
doc.save("poster-" + src.name,
garbage=3, # eliminate duplicate objects
deflate=True, # compress stuff where possible
)
示例

合并单页#
这涉及将 PDF 页面合并起来,形成一个新的 PDF,其中的页面各自组合了原始的两页或四页(也称为“2合1”、“4合1”等)。这可用于创建小册子或缩略图式概览。
import pymupdf
src = pymupdf.open("test.pdf")
doc = pymupdf.open() # empty output PDF
width, height = pymupdf.paper_size("a4") # A4 portrait output page format
r = pymupdf.Rect(0, 0, width, height)
# define the 4 rectangles per page
r1 = r / 2 # top left rect
r2 = r1 + (r1.width, 0, r1.width, 0) # top right
r3 = r1 + (0, r1.height, 0, r1.height) # bottom left
r4 = pymupdf.Rect(r1.br, r.br) # bottom right
# put them in a list
r_tab = [r1, r2, r3, r4]
# now copy input pages to output
for spage in src:
if spage.number % 4 == 0: # create new output page
page = doc.new_page(-1,
width = width,
height = height)
# insert input page into the correct rectangle
page.show_pdf_page(r_tab[spage.number % 4], # select output rect
src, # input document
spage.number) # input page number
# by all means, save new file using garbage collection and compression
doc.save("4up.pdf", garbage=3, deflate=True)
示例

PDF 加密与解密#
从版本 1.16.0 开始,完全支持 PDF 解密和加密(使用密码)。您可以执行以下操作:
检查文档是否受密码保护 /(仍然)已加密(
Document.needs_pass
,Document.is_encrypted
)。获取文档访问授权(
Document.authenticate()
)。使用
Document.save()
或Document.write()
设置 PDF 文件的加密详情,以及解密或加密内容
设置密码
设置加密方法
设置权限详情
注意
PDF 文档可能有两种不同的密码
所有者密码提供完全访问权限,包括更改密码、加密方法或权限详情。
用户密码根据已建立的权限详情提供对文档内容的访问。如果存在,在阅读器中打开 PDF 将需要提供此密码。
Document.authenticate()
方法将根据使用的密码自动建立访问权限。
以下代码片段创建一个新的 PDF,并使用单独的用户密码和所有者密码对其进行加密。允许打印、复制和添加注释,但使用用户密码进行认证的用户不允许进行任何更改。
import pymupdf
text = "some secret information" # keep this data secret
perm = int(
pymupdf.PDF_PERM_ACCESSIBILITY # always use this
| pymupdf.PDF_PERM_PRINT # permit printing
| pymupdf.PDF_PERM_COPY # permit copying
| pymupdf.PDF_PERM_ANNOTATE # permit annotations
)
owner_pass = "owner" # owner password
user_pass = "user" # user password
encrypt_meth = pymupdf.PDF_ENCRYPT_AES_256 # strongest algorithm
doc = pymupdf.open() # empty pdf
page = doc.new_page() # empty page
page.insert_text((50, 72), text) # insert the data
doc.save(
"secret.pdf",
encryption=encrypt_meth, # set the encryption method
owner_pw=owner_pass, # set the owner password
user_pw=user_pass, # set the user password
permissions=perm, # set permissions
)
注意
进一步了解
使用某些阅读器(例如 Nitro Reader 5)打开此文档将反映这些设置

如前所述,在未提供加密参数时,保存时将自动进行解密。
要保留 PDF 的加密方法,请使用 encryption=pymupdf.PDF_ENCRYPT_KEEP
进行保存。如果 doc.can_save_incrementally() == True
,则也可以进行增量保存。
要更改加密方法,请指定上述所有选项(encryption
, owner_pw
, user_pw
, permissions
)。在这种情况下,无法进行增量保存。
API 参考
从 Page 中提取表格#
可以从任何文档Page 中查找和提取表格。
import pymupdf
from pprint import pprint
doc = pymupdf.open("test.pdf") # open document
page = doc[0] # get the 1st page of the document
tabs = page.find_tables() # locate and extract any tables on page
print(f"{len(tabs.tables)} found on {page}") # display number of found tables
if tabs.tables: # at least one table found?
pprint(tabs[0].extract()) # print content of first table
重要
还有一个pdf2docx 提取表格方法,如果您更喜欢,也可以使用它来提取表格。
获取页面链接#
import pymupdf
for page in doc: # iterate the document pages
link = page.first_link # a `Link` object or `None`
while link: # iterate over the links on page
# do something with the link, then:
link = link.next # get next link, last one has `None` in its `next`
获取文档中的所有注释#
页面上的注释(Annot)可以使用 page.annots()
方法获取。
import pymupdf
for page in doc:
for annot in page.annots():
print(f'Annotation on page: {page.number} with type: {annot.type} and rect: {annot.rect}')
从 PDF 中涂黑(删除)内容#
密文处理是特殊类型的注释,可以标记在文档页面上,以指示页面上应安全移除的区域。使用矩形标记一个区域后,此区域将被标记为密文处理;一旦应用密文处理,内容将被安全移除。
例如,如果我们要从文档中涂黑(删除)所有出现的名字“Jane Doe”,我们可以执行以下操作:
import pymupdf
# Open the PDF document
doc = pymupdf.open('test.pdf')
# Iterate over each page of the document
for page in doc:
# Find all instances of "Jane Doe" on the current page
instances = page.search_for("Jane Doe")
# Redact each instance of "Jane Doe" on the current page
for inst in instances:
page.add_redact_annot(inst)
# Apply the redactions to the current page
page.apply_redactions()
# Save the modified document
doc.save('redacted_document.pdf')
# Close the document
doc.close()
另一个示例可以是涂黑(删除)页面上的一个区域,但不对定义区域内的线条艺术(即矢量图形)进行涂黑(删除),通过按如下方式设置参数标志:
import pymupdf
# Open the PDF document
doc = pymupdf.open('test.pdf')
# Get the first page
page = doc[0]
# Add an area to redact
rect = [0,0,200,200]
# Add a redacction annotation which will have a red fill color
page.add_redact_annot(rect, fill=(1,0,0))
# Apply the redactions to the current page, but ignore vector graphics
page.apply_redactions(graphics=0)
# Save the modified document
doc.save('redactied_document.pdf')
# Close the document
doc.close()
警告
一旦保存了文档的密文处理版本,PDF 中的密文处理内容就不可恢复了。因此,文档中的密文处理区域会完全移除该区域的文本和图形。
注意
进一步了解
创建和应用密文处理到页面有几种选项,要了解控制这些选项的参数的完整 API 详情,请参阅 API 参考。
API 参考
转换 PDF 文档#
我们推荐pdf2docx 库,它使用 PyMuPDF 和 python-docx 库提供将 PDF 简单转换为 DOCX 格式的功能。