跳转至

从pymupdf迁移

pylopdf的风格接近pymupdf,但并非直接替代品。影响迁移成本的数据形状——"words" 元组、"dict"结构、search_for → list[Rect]、从1开始的TOC页码——与pymupdf一致, 因此多数提取与页面管理代码只需少量修改。本页列出可直接迁移的部分、行为差异, 以及pylopdf有意不实现的功能应由什么替代。

Note

pylopdf只处理PDF文件。pymupdf打开XPS、EPUB和图像的能力不在其范围内。

快速对照

pymupdf pylopdf 说明
import pymupdffitz为旧名称) import pylopdf
pymupdf.open(path) / open(stream=…) pylopdf.open(path) / open(stream=…) 形式相同,也支持password=,上限127 UTF-8 byte
doc[i]len(doc)、迭代 相同 从0开始,支持负数索引
doc.metadata / set_metadata 相同 键名也相同
page.get_text() 相同 选项:text / words / blocks / dict
page.search_for(t) 相同,并有max_hits=4096 返回有界list[Rect];搜索词上限4,096 byte,max_hits=None取消,无quads=
page.get_pixmap(matrix=pymupdf.Matrix(2, 2)) page.get_pixmap(scale=2) 也可用dpi=144;无Matrix类
pix.samples / width / height / stride / save() 相同 始终为straight-alpha RGBA8;pylopdf有上限的tobytes(max_size=64 MiB)与流式save(path)生成PNG,且save要求.png扩展名
page.get_images() / 提取 page.get_images() 返回带bbox的已绘制图像;JPEG直通
page.get_drawings() 相同 类型化path字典;line/cubic和常用paint/stroke属性;不支持extended=的clip/group层级
doc.rewrite_images(dpi_target=, quality=) doc.compress_images(dpi=, quality=) 将无mask的安全DeviceGray/DeviceRGB DCT/Flate raster转换为JPEG;dpi直接限制最大放置尺寸,不支持lossless转换
doc.selectdelete_page(s)copy_pagenew_page 相同 select重复页码即复制页面
doc.insert_pdf(src, from_page=, to_page=, start_at=) 相同
doc.get_toc() / set_toc() 相同 两者页码均从1开始
doc.save(garbage=4, deflate=True) doc.save(garbage=True, deflate=True, object_streams=True) garbage为bool
doc.save(encryption=…, user_pw=…) doc.save(user_pw=…, owner_pw=…, permissions=…) 仅AES-256;每个password上限127 UTF-8 byte
doc.needs_pass / authenticate() 相同 返回值语义相同(0/1/2/4/6)
page.rect / rotation / set_rotation 相同
page.insert_image(rect, filename= / stream= / pixmap=, rotate=) 相同 JPEG直通、PNG透明、RGBA Pixmap直接复用及顺时针直角旋转;其他编码格式可用Pillow转换
page.show_pdf_page(rect, src, pno) 相同 同一文档会使用原生编辑前快照,无需serialize/open复制
page.insert_text(point, text, fontsize=, fontname=, fontfile=) 相同,另有fontbuffer= / fontindex= 无source时为Standard-14 / WinAnsi,或由pylopdf[cjk]为日文/汉字自动选JP subset;中文本地字形等应显式传font
page.insert_textbox(rect, text, align=, lineheight=) 相同,并支持任意fontfile= / fontbuffer= 同样的可选JP font选择与UAX #14 CJK换行;返回负值时不绘制
page.add_highlight_annot(...) 相同 始终生成appearance stream
doc.embfile_add / names / get / del 相同
doc.get_page_labels / set_page_labelspage.get_label 相同
page.widgets() / widget对象 doc.get_form_fields() / doc.set_form_field(name, value, fontfile=) Document级;文本/选择/复选框/单选按钮的原生外观
page.get_textpage_ocr(...) page.get_text_ocr(...) / page.apply_ocr(...) 通过pylopdf[ocr]使用离线纯Rust PP-OCR;任意带坐标结果仍可传给insert_ocr_text_layer
pymupdf4llm.to_markdown(doc) doc.to_markdown() 内置,MIT

行为差异

  • 坐标:两者均使用左上角原点的显示空间。pylopdf在提取、搜索、绘制和渲染中, 对旋转页面也始终保持同一坐标系。
  • 类型Rect是不可变NamedTuplex0, y0, x1, y1以及width / height)。 没有Point / Matrix / Quad类;API使用普通元组和scale= / dpi=关键字。
  • 过期Page:删除、插入或重排等结构变更后,先前获取的Page会抛出 StalePageError,而不是悄悄指向其他页面。请使用doc[i]重新获取。
  • 异常:基类为PdfErrorValueError的子类);PasswordErrorDocumentClosedErrorEncryptedDocumentErrorStalePageError进一步细分。 except ValueError仍然有效。
  • 资源策略DocumentLimits.web()将传给rendering/extraction的完整PDF snapshot限制为64 MiB,并将累计带位置文本限制为65,536个glyph record。自定义策略 可设置max_interpretation_sizemax_text_glyphsNone保留兼容的无上限行为。
  • get_text选项仅有text / words / blocks / dict,没有html / rawdict / xml。对嵌入字体,span字典包含font和兼容pymupdf的flags (bold/italic/serif/mono)。
  • 多栏文本通过确定性的栏间空白检测排序:先在每栏内从上到下,再按栏从左到右。 小于1 em的窄栏间距只有在两侧都有充分正文且多行密集重复时才会采用;对齐标签、 点引导线以及包含多个分隔位置的密集行仍保持按行顺序。确认后的分栏边界会跟随 扫描件或OCR文本层中的小幅水平漂移。
  • Page.find_tables()可从描边线或细长填充矩形重建轴对齐边框网格, 并支持矩形合并单元格。指定strategy="text"可启用高置信度无边框表格检测; 与对齐的多栏正文之间仍存在几何歧义。使用clip=可只保留完整位于已知显示坐标 区域内的表格;排序无边框结果时可检查Table.confidence / Table.diagnostics
  • to_markdown()按阅读顺序插入完整边框表,并从周围正文中移除单元格文本。 指定table_strategy="text"可加入保守的无边框候选;设为None可禁用表格转换。
  • 表单填写会写入值和原生外观,可在pylopdf及外部查看器中渲染。WinAnsi使用 Helvetica自动缩小;Unicode需传入OpenType字体,或安装pylopdf[cjk]尝试JP subset。中文本地字形与Hangul应传入匹配font。comb文本字段遵循继承的MaxLen与 对齐方式。富文本、pushbutton和签名仍 不在API范围内。
  • CJK竖排文字采用保守检测:列内从上到下,列间从右到左。 尚不解释注音、夹注及横竖混排等复杂排版。

有意不实现的功能 — 使用生态系统

pymupdf功能 pylopdf方案
Story API / insert_htmlbox(排版) 通过typst-py使用typst — 方案
数字签名 pyHanko(MIT)— 方案
增量保存 当前不支持;pylopdf会重写整个文件,并将其保留在观察列表中;签名由pyHanko处理
打开XPS / EPUB / CBZ / 图像 超出范围,只处理PDF

迁移示例

# pymupdf
import pymupdf
doc = pymupdf.open("in.pdf")
page = doc[0]
for rect in page.search_for("合计"):
    page.add_highlight_annot(rect)
pix = page.get_pixmap(matrix=pymupdf.Matrix(2, 2))
pix.save("page.png")
doc.save("out.pdf", garbage=4, deflate=True)
# pylopdf
import pylopdf
doc = pylopdf.open("in.pdf")
page = doc[0]
page.add_highlight_annot(page.search_for("合计"))   # 可直接传入整个列表
page.get_pixmap(scale=2).save("page.png")
doc.save("out.pdf", garbage=True, deflate=True)