使用PyPDF2批量处理多目录PDF时遭遇UnicodeError问题求助
问题分析与解决方案
报错根本原因
从堆栈信息看,PyPDF2在验证文件头时触发Unicode解码失败,核心原因是递归遍历过程中脚本尝试读取了非PDF格式文件(比如临时文件、隐藏文件或其他格式文件)。这类文件的开头不是标准PDF的%PDF标识,导致utf-8解码失败。单独处理文件夹时,这类非PDF文件可能不存在或未被遍历到,因此能正常运行。
同时你的代码存在多处逻辑缺陷,加剧了问题:
- 重复使用
files变量(外层os.walk的files与内层循环变量重名),导致遍历逻辑混乱 - 路径拼接错误:手动拼接字符串容易出现路径层级错误
- 页面循环中反复打开输出文件,会导致内容被多次覆盖
- 手动调用
in_f.close()属于冗余操作,with open会自动管理文件关闭
修复后的代码
from PyPDF2 import PdfFileReader, PdfFileWriter import os source_folder = r'L:\py_test' # 递归遍历目标目录下所有文件 for root, dirs, files in os.walk(source_folder): for file_name in files: # 仅处理PDF文件,过滤非目标格式 if not file_name.lower().endswith('.pdf'): continue file_path = os.path.join(root, file_name) try: with open(file_path, 'rb') as in_f: # 前置检查:验证是否为标准PDF文件 header = in_f.read(4) if header != b'%PDF': print(f"跳过非PDF文件: {file_path}") continue # 重置文件指针至开头 in_f.seek(0) input_pdf = PdfFileReader(in_f) output_pdf = PdfFileWriter() total_pages = input_pdf.getNumPages() print(f"处理文件: {file_path}, 共 {total_pages} 页") need_crop = False for page_idx in range(total_pages): page = input_pdf.getPage(page_idx) page_height = page.mediaBox.getUpperRight_y() print(f"第{page_idx+1}页高度: {page_height} pts") if page_height > 1300: need_crop = True # 修正裁剪坐标:保留底部1220pts区域(如需保留顶部可调换坐标) page.cropBox.upperRight = (page.mediaBox.getUpperRight_x(), page_height) page.cropBox.lowerLeft = (0, page_height - 1220) output_pdf.addPage(page) if need_crop: # 生成新文件路径,避免覆盖原文件 new_file_path = os.path.splitext(file_path)[0] + "_new.pdf" with open(new_file_path, 'wb') as out_f: output_pdf.write(out_f) print(f"已生成裁剪文件: {new_file_path}") else: print(f"{file_path} 所有页面高度≤1300pts,无需裁剪") except Exception as e: print(f"处理文件 {file_path} 出错: {str(e)}") continue
核心修复点
- 严格过滤PDF文件:通过后缀+文件头双重校验,彻底避免读取非PDF文件
- 变量名规范:将内层循环变量改为
file_name,避免与外层files冲突 - 路径拼接优化:使用
os.path.join正确生成递归路径,杜绝手动拼接的层级错误 - 裁剪逻辑修正:修复原代码中反向的裁剪坐标,确保裁剪区域正确
- 输出逻辑优化:处理完所有页面后一次性写入输出文件,避免内容覆盖
- 异常隔离:添加
try-except捕获单个文件的处理错误,保证递归流程不中断
内容的提问来源于stack exchange,提问作者Camerak
相关产品推荐
相关产品推荐

