PyPDF2合并PDF丢页或报PageObject错,因PdfMerger引用原文件页对象而非深拷贝,需以rb模式打开并全程保持文件句柄开启;加密PDF须先decrypt();禁用旧版addPage,统一用append()。

用 PyPDF2 合并 PDF 时为什么总丢页或报 PageObject 错?
PyPDF2 的 PdfMerger 是最轻量的合并方案,但它的底层逻辑是“引用原文件页对象”,不是深拷贝。一旦源 PDF 被关闭、或读取时用了 strict=False 忽略错误,后续追加页就可能失效。
- 合并前必须确保所有输入文件都以
rb模式打开,并全程保持打开状态(不能先read()再关掉) - 遇到加密 PDF,
merger.append(pdf_file, pages=(0, None))会直接抛NotImplementedError,得先用decrypt()解密 - 不要混用
PdfReader和PdfMerger的旧版写法(比如手动调addPage),新版merge()/append()才稳定
from PyPDF2 import PdfMerger
merger = PdfMerger()
for f in ["a.pdf", "b.pdf"]:
with open(f, "rb") as fp:
merger.append(fp) # 注意:fp 不能提前 close()
with open("out.pdf", "wb") as out:
merger.write(out)
拆分多页 PDF 时怎么按逻辑块(比如每章)切,而不是固定页数?
靠页码数字硬切(如每 10 页一拆)在真实文档里基本不可用——目录页、封面、附录、页眉页脚都会打乱节奏。真正靠谱的是结合文本内容定位,比如找“第 X 章”或“Appendix”字样所在页。
-
PyPDF2提取文本能力弱,遇到扫描件或含图 PDF 就返回空字符串;优先用pdfplumber,它能保留坐标和字体信息,适合做规则匹配 - 别在循环里反复调
page.extract_text(),先缓存全部文本再正则扫一遍,效率高 5 倍以上 - 拆分后保存要用
PdfWriter,且必须显式调add_page(),不能直接写pages列表
import pdfplumber
with pdfplumber.open("book.pdf") as pdf:
texts = [p.extract_text() or "" for p in pdf.pages]
# 找到所有“Chapter ”开头的页索引
chapters = [i for i, t in enumerate(texts) if t.startswith("Chapter ")]
提取 PDF 里的矢量文本为啥复制出来全是乱码或空格?
PDF 文本不是线性存储的,而是由带坐标的 Tj / TJ 操作符拼出来的。字体嵌入方式、编码映射(如 WinAnsiEncoding)、甚至文字方向(竖排中文)都会让原始字节无法直译。
-
pdfplumber默认用layout=True,能还原阅读顺序,比PyPDF2的纯流式提取准得多 - 如果文本看着正常但复制粘贴错位,大概率是 PDF 用了自定义字体子集(subset),这时得开
use_text_flow=True强制重排 - 英文 PDF 中的连字(如
fi,fl)会被合成为一个 glyph,需用chars层级数据手动替换
with pdfplumber.open("doc.pdf") as pdf:
page = pdf.pages[0]
# 获取字符级数据,含 x/y/字体/大小
chars = page.chars
# 过滤掉极小字号(水印)或超宽间距(装饰线)
text = "".join(c["text"] for c in chars if c["size"] > 6)
怎么把 PDF 里内嵌的图片原样导出为 PNG/JPEG,不模糊不拉伸?
PDF 图片本质是对象流(XObject),可能是 JPEG 原生、CCITT 黑白压缩、或 Flate 压缩的 RGB 数据。直接转 PIL.Image 容易丢色域或解错压缩类型。
立即学习“Python免费学习笔记(深入)”;
- 先用
pdfplumber的page.images列出所有图片对象,注意src字段是原始二进制,不是路径 - 对
type == "jpeg"的,直接写入文件即可;对"png"或"other",需检查filter字段(如/FlateDecode)再解压 - 导出尺寸不等于显示尺寸:PDF 用
matrix变换缩放,得用x0/y0/x1/y1计算实际像素宽高,否则图会糊
for img in page.images:
if img["src"]:
with open(f"img_{img['x0']:.0f}_{img['y0']:.0f}.png", "wb") as f:
f.write(img["src"])
PDF 的文本与图像混合结构决定了它没法靠一个库全搞定。你得根据目标切换工具链:合并拆分用 PyPDF2,内容分析用 pdfplumber,高压缩或扫描件才上 pdf2image + OCR。别指望一次读取就拿到“干净文本+高清图”,那是两个不同维度的问题。










