本文介绍使用 PyMuPDF(fitz)替代 pdf2image,无需安装 poppler 即可将多页 PDF 高效转换为内存中的图像字节对象,完美适配 LazyDocument 等依赖 images 参数的文档处理流程。
本文介绍使用 pymupdf(fitz)替代 pdf2image,无需安装 poppler 即可将多页 pdf 高效转换为内存中的图像字节对象,完美适配 lazydocument 等依赖 `images` 参数的文档处理流程。
PyMuPDF 是一个功能强大、纯 Python 友好且无需外部依赖(如 poppler) 的 PDF 处理库,其核心模块 fitz 内置了高质量的渲染引擎,可直接将 PDF 页面转换为像素图(Pixmap),并支持以多种格式(PNG、JPEG 等)导出为字节流——这正是 LazyDocument 所需的 images 参数类型(List[bytes] 或 List[io.BytesIO])。
以下是一个完整、生产就绪的实现方案,适用于 S3 存储的 PDF 文件,并与您原有的 Textract 流程无缝集成:
import fitz # pip install PyMuPDF
import boto3
from io import BytesIO
def pdf_bytes_to_image_bytes_list(pdf_bytes: bytes, dpi: int = 150) -> list[bytes]:
"""
将 PDF 字节数据转换为 PNG 图像字节列表(每页一张)
:param pdf_bytes: PDF 文件原始字节(如从 S3 get_object().read() 获取)
:param dpi: 渲染分辨率,默认 150,兼顾清晰度与内存占用
:return: 每个元素为 PNG 格式 bytes 的列表
"""
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
images = []
for page in doc:
# 渲染为 Pixmap(支持 alpha、抗锯齿、指定 DPI)
pix = page.get_pixmap(dpi=dpi, matrix=fitz.Matrix(1, 1)) # matrix 可用于缩放/旋转
# 转为 PNG 字节(无文件 I/O,全部在内存中完成)
images.append(pix.tobytes("png"))
doc.close()
return images
# ✅ 替换原代码中 pdf2image 的部分
s3_client = boto3.client("s3", region_name="us-east-1")
file_obj = s3_client.get_object(Bucket=bucket, Key=key)
pdf_bytes = file_obj["Body"].read()
# 关键替换:用 PyMuPDF 生成 images 列表
images = pdf_bytes_to_image_bytes_list(pdf_bytes, dpi=150)
LazyDoc = LazyDocument(
response["JobId"],
Textract_API.ANALYZE,
textract_client=textract_client,
images=images, # ✅ 类型完全兼容:List[bytes]
output_config=output_config,
)
✅ 优势总结:
- 零外部依赖:无需 poppler、无需配置 poppler_path,pip install PyMuPDF 后开箱即用;
- 内存友好:全程基于字节流操作,避免临时文件写入,符合云环境(如 Lambda、受限容器)部署要求;
- 可控性强:支持自定义 DPI、色彩空间(colorspace=fitz.csRGB)、是否启用抗锯齿(alpha=True)、甚至单页裁剪或区域渲染;
- 性能优异:PyMuPDF 渲染速度通常优于 pdf2image + poppler 组合,尤其在多页文档场景下。
⚠️ 注意事项:
- 若 PDF 含复杂字体或嵌入 ICC 配置文件,建议保持 dpi ≥ 120 以保障 OCR 可读性;
- pix.tobytes("jpeg") 可减小体积,但会损失文本边缘精度,推荐优先使用 "png";
- 对超长文档(>100 页),可考虑分批处理或增加 gc.collect() 避免内存累积。
至此,您已成功绕过 PDFInfoNotInstalledError,构建了一条稳定、合规、高性能的 PDF → 图像 → Textract → LazyDocument 全链路。











