用 Python 实现 Word 批量转“高保真”PDF
一键导出,效果堪比手动“另存为”
在日常工作中,我们经常需要把多份 Word 文档(合同、标书、报告、简历)批量转成 PDF。 有没有办法既批量处理,又完美还原 Word 里的效果? 答案是有的——只要调用 Word 本身的“另存为 PDF”引擎。
今天分享一个我一直在用的 Python 脚本:批量、高保真、稳定,转换出来的 PDF 和手动“另存为”几乎一模一样。
一、脚本核心亮点
| |
|---|
| 完全采用 Word 的 ExportAsFixedFormat 接口,参数调优至最接近手动“另存为” |
| 自动扫描 result 文件夹下所有 .docx 文件,输出到 result_pdf |
| |
| |
| 使用 win32com 直接控制 Word 进程,资源占用低 |
| 关键参数 BitmapMissingFonts=True 把缺失字体转成位图,彻底避免字体替代导致的数字变形 |
经过几十份文档实测(含复杂表格、图表、域代码),转换结果与手动“另存为”肉眼无法区分。
二、完整代码
- 【我】最初时AI最初建议
UseISO19005_1 设为False。但是当设为True 时,可以解决用网页打开pdf查看Times New Roman数字时不够保真的问题(用Acrobat打开查看时渲染又没有问题,且数值依然是Times New Roman字体)。⭐⭐ - 【我】建议对转换后的pdf文件进行全面检查,然后对脚本进行优化。
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""Windows 下批量将 result 目录中的 docx 转为 PDF(高保真版本)核心目标:1. 尽量接近 Word 手动“另存为 PDF”的效果2. 解决浏览器查看数字显示异常 / 字体替代概率3. 稳定批量转换4. 输出日志依赖:pip install pywin32要求:本机安装 Microsoft Word"""import sysimport timeimport tracebackfrom pathlib import Pathimport win32com.clientimport pythoncom# ===============================# 配置区域# ===============================INPUT_DIR = Path("result") # docx目录OUTPUT_DIR = Path("result_pdf") # pdf输出目录LOG_FILE = Path("convert.log")VISIBLE = False # 是否显示Word界面RETRY = 2 # 失败重试次数# ===============================# 日志函数# ===============================def log(msg): text = f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}"print(text) with open(LOG_FILE, "a", encoding="utf-8") as f: f.write(text + "\n")# ===============================# 启动 Word# ===============================def start_word(): pythoncom.CoInitialize() word = win32com.client.DispatchEx("Word.Application") word.Visible = VISIBLE word.DisplayAlerts = 0 word.ScreenUpdating = Falsereturn word# ===============================# 关闭 Word# ===============================def stop_word(word): try: word.Quit() except: pass pythoncom.CoUninitialize()# ===============================# 高保真导出 PDF# ===============================def export_pdf(word, docx_file, pdf_file):""" 最接近手动另存为 PDF 的方式 """ doc = None try: doc = word.Documents.Open( str(docx_file.resolve()), ReadOnly=True, AddToRecentFiles=False, Visible=False )# 更新目录 / 域(可选) try: doc.Fields.Update() except: pass# 高保真导出 doc.ExportAsFixedFormat( OutputFileName=str(pdf_file.resolve()), ExportFormat=17, # wdExportFormatPDF OpenAfterExport=False, OptimizeFor=0, # Print quality Range=0, # all document Item=0, # content only IncludeDocProps=True, KeepIRM=True, CreateBookmarks=1, # headings DocStructureTags=True, BitmapMissingFonts=True, # 字体缺失转位图,避免数字异常 UseISO19005_1=True # 非PDF/A,兼容性更好 # ⭐ 但是设为True能解决 Times New Roman中转换后,网页打开查看不够保真,但是Acrobat 又保真的问题。 ) doc.Close(False) except Exception:if doc: try: doc.Close(False) except: pass raise# ===============================# 单文件转换(带重试)# ===============================def convert_one(word, docx_file): pdf_file = OUTPUT_DIR / (docx_file.stem + ".pdf")for i in range(RETRY + 1): try: export_pdf(word, docx_file, pdf_file) size = pdf_file.stat().st_size / 1024log(f"成功: {docx_file.name} -> {pdf_file.name} ({size:.1f} KB)")return True except Exception as e:log(f"失败[{i+1}] {docx_file.name}: {e}")if i < RETRY: time.sleep(2)return False# ===============================# 主程序# ===============================def main(): OUTPUT_DIR.mkdir(exist_ok=True) files = sorted(INPUT_DIR.glob("*.docx"))if not files:log("未找到 docx 文件")returnlog(f"发现 {len(files)} 个文件") word = start_word() success = 0 fail = 0 try:for f in files: ok = convert_one(word, f)if ok: success += 1else: fail += 1 except KeyboardInterrupt:log("用户中断") except Exception:log(traceback.format_exc()) finally: stop_word(word)log("=" * 50)log(f"完成 成功:{success} 失败:{fail}")if __name__ == "__main__": main()
三、使用步骤(小白也能上手)
1️⃣ 环境要求
操作系统:Windows(Win7 / 10 / 11 均可)
软件:已安装 Microsoft Word(Office 2010 及以上版本)
Python:Python 3.6 或更高版本(下载地址)
2️⃣ 安装依赖
打开命令提示符(或 PowerShell),执行:
pip install pywin32
3️⃣ 准备文件夹
在你存放脚本的目录下,手动创建一个名为 result 的文件夹。把所有需要转换的 .docx 文件放进去。
4️⃣ 运行脚本
在终端中执行:
python docx2pdf_highfidelity.py
5️⃣ 获取结果
转换成功的 PDF 会出现在新生成的 result_pdf 文件夹中。
转换日志保存在 convert.log 文件里,方便排查报错。
四、关键技术解析(为什么要这样写)
很多朋友好奇:为什么网上那么多转换方案,偏偏这套能解决“数字异常”问题?
关键在 ExportAsFixedFormat 的这一行参数:
BitmapMissingFonts=True
当目标系统(比如某人的浏览器)没有文档里用到的字体(例如 Times New Roman、Calibri)时,普通转换工具会偷偷用其他字体替代,导致数字、符号形状改变。
设置 BitmapMissingFonts=True 后,Word 会把缺失字体的文字渲染成图片嵌入 PDF。虽然文件体积会增大一点点,但保真度瞬间拉满——任何设备打开,看到的都和原文档一模一样。
另一个容易忽略的参数:
UseISO19005_1=False# 非 PDF/A 模式
很多教程提倡导出 PDF/A(用于长期归档),但这会限制某些动态元素(如表单、视频)。
为了让普通读者在浏览器里直接打开、复制文字、查看超链接,我们选择标准 PDF 模式,兼容性最佳。
五、注意事项
| |
|---|
运行后提示 ModuleNotFoundError: No module named 'win32com' | 重新执行 pip install pywin32,然后重启命令行 |
| 检查 VISIBLE = False 是否被改成了 True;确认没有其他 Word 进程残留,可以打开任务管理器结束 WINWORD.EXE |
| 检查原文档中表格边框是否设置为“无颜色”或“自动”,手动设为实线即可 |
| 脚本每处理一个文件会关闭该文档,不会同时打开多个;如果转换几百个文件,建议分批次 |
| 确保 result 和 result_pdf 文件夹没有被其他程序占用,且脚本有写入权限 |
六、结语
如果你也在为批量转 PDF 烦恼,不妨试试它。
如果你的电脑上没有 Word,或者使用 Mac / Linux,也可以尝试用 unoconv 或 LibreOffice 命令行,但保真度大概率不如本方案。
希望这篇推文能帮你节省大量重复劳动的时间。