适用人群 :Mac 用户、办公族、科研人员、PDF 处理爱好者
关键词:macOS PDF 乱码、预览打不开 PDF、Python 批量修复 PDF、PyMuPDF、PDF 转图像
🔍 问题背景
你是否遇到过这种情况?
- 在 Chrome、Safari 等浏览器中能正常查看 PDF;
- 但用 macOS 自带的 "预览"(Preview)或 PDF 阅读器打开时,页面空白或显示乱码?
这通常不是文件损坏,而是 PDF 使用了非标准字体嵌入、JavaScript、表单字段或特殊编码,而 macOS 预览对这些特性支持有限。
💡 根本原因:PDF 结构不规范,但浏览器"容错能力强",本地阅读器则严格解析失败。
✅ 解决思路:用"图像化"绕过所有兼容性问题
最可靠、通用的解决方案是:
将每一页 PDF 渲染为高分辨率图片,再重新封装成新的 PDF 文件。
这样生成的 PDF:
- 不依赖任何字体;
- 无 JavaScript/表单等复杂元素;
- 100% 兼容所有设备和阅读器(包括 iPhone、iPad、Windows、Mac);
- 唯一代价:文件体积略大 + 无法复制文本(若原始是扫描件则无影响)。
🐍 自动化脚本:一键批量修复
下面是一个用 Python + PyMuPDF(fitz) 编写的脚本,专为 Mac 用户设计,支持:
- 自动从
PDF/文件夹读取问题文件; - 修复后统一输出到
repairPdf/文件夹; - 可配置 DPI、文件名后缀、输入/输出目录名;
- 无需命令行参数,开箱即用!
📜 完整脚本(含详细中文注释)
python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
【Mac PDF 乱码修复工具】
功能:将无法在"预览"中正常显示的 PDF 转换为纯图像 PDF,确保全平台兼容。
原理:逐页渲染 PDF 为 PNG 图像,再合成新 PDF。
✅ 使用方法:
1. 将本脚本放在任意文件夹(如 ~/Desktop/AITools/)
2. 在同级目录创建 "originalPDF" 文件夹,放入所有有问题的 PDF
3. 终端运行:python3 repair_pdf.py
4. 修复后的文件自动保存到同级 "repairPDF" 文件夹
🔧 配置说明:
- 所有可调参数集中在顶部,修改方便
- 支持自定义 DPI(清晰度)、是否加 "_fixed" 后缀等
作者:JCode(基于 Qwen 技术支持)
"""
import os
import sys
import fitz # PyMuPDF:强大的 PDF 处理库
# ==============================
# 🔧 用户配置区(按需修改这里)
# ==============================
INPUT_FOLDER_NAME = "originalPDF" # 原始 PDF 所在的子文件夹名(必须存在)
OUTPUT_FOLDER_NAME = "repairPDF" # 修复后 PDF 保存的子文件夹名(会自动创建)
DPI = 150 # 渲染分辨率(单位:dots per inch)
# 推荐值:150(普通文档)、200(小字号/图表)、300(印刷级)
ADD_FIXED_SUFFIX = True # 是否在输出文件名后添加 "_fixed" 后缀
# 设为 False 则保留原文件名(注意:可能覆盖!)
# ==============================
def repair_pdf(input_path, output_path, dpi=150):
"""
修复单个 PDF 文件:将其每一页转为图像,再合并为新 PDF
:param input_path: 原始 PDF 的完整路径
:param output_path: 修复后 PDF 的完整路径
:param dpi: 渲染分辨率,越高越清晰但文件越大
"""
try:
# 打开原始 PDF 文档
doc = fitz.open(input_path)
# 创建一个新的空 PDF 文档用于输出
new_doc = fitz.open()
# 创建缩放矩阵:PDF 默认 DPI 是 72,所以 (dpi / 72) 是缩放比例
mat = fitz.Matrix(dpi / 72, dpi / 72)
# 遍历每一页
for page_num in range(doc.page_count):
page = doc[page_num]
# 将页面渲染为位图(alpha=False 表示不带透明通道,减小体积)
pix = page.get_pixmap(matrix=mat, alpha=False)
# 将图像转为 PNG 字节流(也可用 "jpeg",但 PNG 无损更安全)
img_data = pix.tobytes("png")
# 定义图像插入区域(从左上角 0,0 开始,宽高为图像尺寸)
img_rect = fitz.Rect(0, 0, pix.width, pix.height)
# 在新 PDF 中新建一页,尺寸与图像一致
new_page = new_doc.new_page(width=pix.width, height=pix.height)
# 将图像插入该页
new_page.insert_image(img_rect, stream=img_data)
# 保存新 PDF(garbage=4 清理冗余对象,deflate=True 压缩)
new_doc.save(output_path, garbage=4, deflate=True)
new_doc.close()
doc.close()
print(f"✅ 已修复: {os.path.basename(output_path)}")
except Exception as e:
print(f"❌ 处理失败 {input_path}: {e}")
def batch_repair(input_folder, output_folder, dpi=150, add_suffix=True):
"""
批量处理指定文件夹内的所有 PDF 文件
:param input_folder: 输入文件夹路径
:param output_folder: 输出文件夹路径(会自动创建)
:param dpi: 渲染 DPI
:param add_suffix: 是否添加 "_fixed" 后缀
"""
# 检查输入文件夹是否存在
if not os.path.isdir(input_folder):
print(f"错误:输入文件夹不存在 → {input_folder}")
return
# 自动创建输出文件夹(exist_ok=True 表示如果已存在也不报错)
os.makedirs(output_folder, exist_ok=True)
# 列出所有 .pdf 文件(不区分大小写)
pdf_files = [
f for f in os.listdir(input_folder)
if f.lower().endswith('.pdf')
]
if not pdf_files:
print("⚠️ 输入文件夹中没有找到 PDF 文件")
return
# 逐个处理
for filename in pdf_files:
input_file = os.path.join(input_folder, filename)
base_name = os.path.splitext(filename)[0] # 去掉 .pdf 后缀
if add_suffix:
output_filename = f"{base_name}_fixed.pdf"
else:
output_filename = f"{base_name}.pdf" # 谨慎:可能覆盖原始文件!
output_file = os.path.join(output_folder, output_filename)
repair_pdf(input_file, output_file, dpi=dpi)
if __name__ == "__main__":
# 自动获取脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 构建输入/输出文件夹的绝对路径
input_dir = os.path.join(script_dir, INPUT_FOLDER_NAME)
output_dir = os.path.join(script_dir, OUTPUT_FOLDER_NAME)
# 打印当前配置,便于用户确认
print(f"⚙️ 配置:")
print(f" 输入文件夹: {input_dir}")
print(f" 输出文件夹: {output_dir}")
print(f" DPI: {DPI}")
print(f" 添加 '_fixed' 后缀: {ADD_FIXED_SUFFIX}")
print("-" * 50)
# 执行批量修复
batch_repair(
input_folder=input_dir,
output_folder=output_dir,
dpi=DPI,
add_suffix=ADD_FIXED_SUFFIX
)
print("-" * 50)
print(f"🎉 修复完成!结果已保存至:\n{output_dir}")
▶️ 使用步骤(超简单)
-
安装依赖(只需一次):
pip3 install PyMuPDF -
准备文件夹结构(以桌面为例):
javascript~/Desktop/AITools/ ├── originalPDF/ ← 把乱码 PDF 全放这里 ├── repairPDF/ ← 修复好的 PDF 会放这里 └── repair_pdf.py ← 本脚本 -
运行脚本:
javascriptcd ~/Desktop/AITools python3 repair_pdf.py -
查看结果:
- 修复后的 PDF 会出现在
AITools/repairPdf/; - 文件名如
report_fixed.pdf; - 用"预览"打开,一切正常!
- 修复后的 PDF 会出现在
⚠️ 注意事项
- 文本不可复制 :因为 PDF 已转为图像。如果你需要可搜索文本,请考虑
ocrmypdf(需额外安装 Tesseract OCR)。 - 文件体积增大:150 DPI 下,一页约 200~500 KB。可通过降低 DPI(如 120)减小体积。
- 不适用于加密 PDF:脚本无法处理密码保护的文件。
💡 进阶建议
- 添加右键服务:用 Automator 封装此脚本,实现"选中文件夹 → 右键修复";
- 集成 OCR:在图像 PDF 上叠加 OCR 层,兼顾兼容性与可搜索性;
- GUI 版本:用 Tkinter 或 PyQt 做图形界面,适合非技术用户。
🙌 结语
这个小工具解决了我在 Mac 上长期被 PDF 乱码困扰的问题。希望它也能帮到你!如果你觉得有用,欢迎点赞、收藏、转发给同样被"预览打不开 PDF"折磨的朋友。
祝你 PDF 从此不再乱码,工作更高效! 🎄(正好今天是平安夜 😊)