PyMuPDF 1.24.4 中文文档(一)(4)https://developer.aliyun.com/article/1559434
复制页面
要复制页面,请执行以下操作:
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
注意
API 参考
Document.copy_page()
选择页面
要选择页面,请执行以下操作:
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 参考手册的 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 参考
Document.select()
添加空白页
要添加空白页面,请执行以下操作:
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”,则返回横向版本。
这里是一个三行代码,创建一个带有一个空白页面的 PDF,文件大小为 460 字节:
doc = pymupdf.open() doc.new_page() doc.save("A4.pdf")
API 参考
Document.new_page()
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)
注意
进一步探索
文本参数可以是字符串或字符串序列(假设使用 UTF-8 编码)。插入将从点(50, 72)开始,这是页面顶部下方一英寸处并距离左侧 50 点。返回插入的文本行数。
API 参考
Document.insert_page()
分割单页
这处理将 PDF 页面分割为任意片段。例如,您可能有一个带有 Letter 格式页面的 PDF,您希望将其以 4 倍放大比例打印:每个页面被分割成 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 )
示例:
注意
API 参考
Page.cropbox_position()
Page.show_pdf_page()
合并单页
这涉及将 PDF 页面连接起来形成一个新的 PDF,其中每个页面组合两个或四个原始页面(也称为“2-up”,“4-up”等)。这可以用于创建小册子或类似缩略图的概览。
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)
示例:
注意
API 参考
Page.cropbox_position()
Page.show_pdf_page()
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 参考
Document.save()
从页面提取表格
可以从任何文档中找到并提取表格 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
注意
API 参考
Page.find_tables()
重要
你也可以选择使用 pdf2docx 提取表格方法。
获取页面链接
可以从 Page 中提取链接以返回 Link 对象。
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`
注意
API 参考
Page.first_link()
从文档获取所有注释
页面上的注释 (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}')
注意
API 参考
Page.annots()
从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 参考
Page.add_redact_annot()
Page.apply_redactions()
转换 PDF 文档
我们推荐使用 pdf2docx 库,该库使用 PyMuPDF 和 python-docx 库提供从 PDF 到 DOCX 格式的简单文档转换。
对本页有任何反馈吗?
此软件按原样提供,不附带任何明示或暗示的保证。此软件根据许可证分发,未经授权不得复制、修改或分发。请参阅 artifex.com 上的许可信息或联系位于美国加利福尼亚州旧金山 Mesa 街 39 号 108A 室的 Artifex Software Inc. 获取更多信息。
此文档涵盖所有版本直至 1.24.4。