
一个 PDF 丢过来,要抽文字、找指定页、拆文件、转图片,最后还得重新合成。
这种活看着不难,真写起来最烦。换几个库来回倒数据不说,碰上页数多一点的文件,处理速度也容易让人怀疑人生。
我现在碰到 PDF 批处理,第一反应基本就是 PyMuPDF。
安装也没什么花活:
pip install pymupdf
代码里直接:
import pymupdf
doc = pymupdf.open("contract.pdf")
print("页数:", doc.page_count)
PyMuPDF 能干的事情不少,文本提取、页面渲染、拆分、合并、加水印这些都在一个库里。官方文档里的 Page.get_text()、Page.get_pixmap()、Document.insert_pdf() 也是我平时最常碰的几个接口。
但我一般不会上来就写一个“读取 PDF 并打印 Hello World”的例子,那种代码工作里基本没什么用。
假设现在有一批合同 PDF,要找出包含“合同编号”和“甲方”的页面,把命中的页面单独抽出来。
我会这么写:
from pathlib import Path
import pymupdf
def pick_contract_pages(src_file: str, out_file: str):
source = pymupdf.open(src_file)
picked = pymupdf.open()
for page_no, page in enumerate(source):
text = page.get_text("text", sort=True)
hit_contract = "合同编号" in text
hit_party = "甲方" in text
if not (hit_contract and hit_party):
continue
print(f"命中第 {page_no + 1} 页")
picked.insert_pdf(source, from_page=page_no, to_page=page_no)
if picked.page_count == 0:
print(f"没找到目标页:{Path(src_file).name}")
return
picked.save(out_file, garbage=4, deflate=True)
picked.close()
source.close()
pick_contract_pages(
"incoming/customer_contract.pdf",
"output/contract_pages.pdf"
)
这段代码我比较喜欢的一点,是不用先把 PDF 拆成十几个临时文件,再一个个合回去。
直接在内存里的新文档对象上 insert_pdf() 就行。
而且提取文本时,我通常会顺手加上 sort=True。PDF 里的文字存储顺序未必就是人眼看到的从上到下,官方文档也专门提醒过这个问题,sort=True 可以按页面位置重新排序。
不过这里有个坑。
如果你跑:
text = page.get_text("text")
结果发现:
''
先别怀疑编码。
我碰这种情况第一件事不是改 UTF-8,而是直接打开 PDF 看它到底是真文字,还是扫描图片。
纯扫描版 PDF 本身没有可提取的文本层,get_text() 自然拿不到你肉眼看到的字。PyMuPDF 的文本提取针对的是 PDF 中已有的文本内容,不会因为图片里“看起来有字”就自动变成文字。
这种文件要走 OCR,处理思路已经是另一回事了。
还有一个我用得很多的功能:PDF 转图片。
比如线上收到一个 PDF,反馈“第 7 页排版错了”。我一般懒得人工截图,直接把指定页面渲染出来:
import pymupdf
def export_preview(pdf_file: str, pages: list[int]):
doc = pymupdf.open(pdf_file)
for page_no in pages:
if page_no < 1 or page_no > doc.page_count:
print(f"跳过非法页码: {page_no}")
continue
page = doc[page_no - 1]
pix = page.get_pixmap(dpi=160, alpha=False)
target = f"preview/page_{page_no}.png"
pix.save(target)
print("已生成:", target)
doc.close()
export_preview("report.pdf", [1, 7, 12])
get_pixmap() 这东西挺实用,调 DPI 就能控制输出图片清晰度,没必要自己研究 PDF 怎么画到 Canvas 上。官方接口也直接支持通过 dpi 控制渲染分辨率。
还有一种需求我见得更多:月底十几个 PDF 报告,最后要拼成一个总文件。
这种我不会碰命令行工具,Python 几行就够了:
from pathlib import Path
import pymupdf
def merge_reports(folder: str, target: str):
result = pymupdf.open()
files = sorted(Path(folder).glob("*.pdf"))
for pdf_file in files:
current = pymupdf.open(pdf_file)
if current.page_count == 0:
current.close()
continue
result.insert_pdf(current)
print(f"合并 {pdf_file.name},{current.page_count} 页")
current.close()
if result.page_count:
result.save(target, garbage=4, deflate=True)
result.close()
merge_reports("monthly_reports", "output/monthly_all.pdf")
这里我会多留一个心眼:批量跑文件时,该 close() 的就关掉。
尤其是定时任务一次扫很多 PDF,文件句柄一直挂着,最后报错的时候,你很容易把锅甩给 PDF 文件损坏,实际上是自己的资源没释放。
PyMuPDF 给我的感觉不是“API 特别优雅”,而是干活比较直接。
我要文字,就 get_text()。
我要图片,就 get_pixmap()。
我要拆页、拼页,就操作 Document。
很多 PDF 需求根本没必要上来搞一套很重的处理链路。先看看 PyMuPDF 能不能直接做,十有八九,代码会比你预想得短。
以上就是“模块化笔记本电脑制造商Framework翻倍式提高价格 因为内存价格还在继续涨价”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。
扫码二维码 获取免费视频学习资料

- 本文固定链接: http://www.phpxs.com/post/14469/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料