odoo-068 pdf 批量转 img,及 os、 PyMuPDF
文章目录
- PDF 文件批量转换成 图片
- 安装必要的库
- 转换脚本
- 上面使用到相关类 (os, PyMuPDF)
- os 相关用法
- 目录与文件操作
- 路径操作 (os.path子模块)
- 系统信息与操作
- 实用技巧与注意事项
- PyMuPDF 相关用法
PDF 文件批量转换成 图片
需求:把文件夹中的所有pdf格式的发票一次转换成图片。
使用PyMuPDF(fitz)库是批量转换的强力选择,Pillow(PIL)是一个常用的图像处理库,有时在保存图像格式时很有用。
安装必要的库
方法一:pip 安装
pip install PyMuPDF Pillow
方法二:在设置中搜索 安装 ,版本我选择的1.19.0
转换脚本
# coding:utf-8import fitz # PyMuPDF
import osdef pdf_to_img(pdf_folder, output_base_path, dpi=300, zoom=3):"""将指定文件夹中的所有PDF文件转换为图片参数:pdf_folder: 存放PDF文件的文件夹路径output_base_path: 图片输出根目录dpi: 输出图片分辨率,默认为300zoom: 缩放因子,默认为3,用于提高清晰度"""# 确保输出目录存在if not os.path.exists(output_base_path):os.makedirs(output_base_path)# 获取文件夹中所有PDF文件pdf_files = [f for f in os.listdir(pdf_folder) if f.lower().endswith('.pdf')]for pdf_file in pdf_files:# 构建完整的PDF文件路径pdf_path = os.path.join(pdf_folder, pdf_file)# 为每个PDF创建一个子文件夹,以PDF文件名(不含扩展名)命名# subfolder_name = os.path.splitext(pdf_file)[0]# save_path = os.path.join(output_base_path, subfolder_name)# 上面两行会为每一个图片创建一个子文件夹,# 下面所有图片文件放到一个文件夹中save_path = os.path.join(output_base_path)if not os.path.exists(save_path):os.makedirs(save_path)# 打开PDF文档doc = fitz.open(pdf_path)print(f"正在处理: {pdf_file}, 共 {len(doc)} 页...")# 逐页转换for page_num in range(len(doc)):page = doc.load_page(page_num)# 设置缩放矩阵以提高分辨率,根据zoom参数和dpi进行调整# 创建了一个缩放矩阵,主要用于控制将 PDF 页面转换为图像(如 PNG)时的分辨率和清晰度mat = fitz.Matrix(zoom, zoom)pix = page.get_pixmap(matrix=mat, dpi=dpi)# 构建图片输出路径和文件名image_filename = f"page_{pdf_files.index(pdf_file)+1:03d}.png" # 生成带序号的文件名,如page_001.pngimage_path = os.path.join(save_path, image_filename)# 保存图片pix.save(image_path)doc.close()print(f"已完成: {pdf_file} -> 保存至 {save_path}")print("所有PDF文件转换完成!")# 使用示例
if __name__ == "__main__":# 修改为PDF文件夹路径 (我这里是在根目录下,使用的相对路径)your_pdf_folder = "pdf_files"# 修改为输出文件夹路径your_output_folder = "img_files"pdf_to_img(your_pdf_folder, your_output_folder, dpi=300, zoom=3)
上面使用到相关类 (os, PyMuPDF)
os 相关用法
Python 的 os模块是处理文件和目录,以及与操作系统交互的利器。
目录与文件操作
方法 | 作用说明 | 示例 |
---|---|---|
os.getcwd() | 获取当前工作目录 (Current Working Directory) 的路径 | print(os.getcwd()) # 输出: /home/user/projects |
os.chdir(path) | 改变当前工作目录到指定路径 | os.chdir(‘/tmp’) |
os.listdir(path=‘.’) | 返回指定路径下的文件和子目录列表 (默认是当前目录) | files = os.listdir(‘/tmp’) # 返回列表[‘file1.txt’, ‘dir1’] |
os.mkdir(path) | 创建单级目录 | os.mkdir(‘new_dir’) |
os.makedirs(path) | 递归创建多级目录 | os.makedirs(‘parent/child/grandchild’) |
os.rmdir(path) | 删除空目录 | os.rmdir(‘empty_dir’) |
os.removedirs(path) | 递归删除空目录,从子目录逐级向上删除,直到遇到非空目录为止 | os.removedirs(‘parent/child/grandchild’) |
os.remove(path) | 删除一个文件 | os.remove(‘old_file.txt’) |
os.rename(src, dst) | 重命名文件或目录,也可用于移动文件(如果目标路径不同) | os.rename(‘old.txt’, ‘new.txt’) |
os.walk(top) | 遍历目录树,生成每个目录中的文件名和子目录名,常用于批量处理文件 | 详见下方代码示例 |
# os.walk(top)示例:生成器,每次产生一个三元组 (当前目录路径, 子目录列表, 文件列表)。
for root_dir, sub_dirs, files in os.walk('/path/to/start'):print(f"在目录 {root_dir} 中:")print(f" 子目录: {sub_dirs}")print(f" 文件: {files}")
路径操作 (os.path子模块)
os.path 用于高效地操作和解析文件路径。
方法 | 作用说明 | 示例 |
---|---|---|
os.path.join(a, b, …) | 智能拼接多个路径部分,使用当前系统的路径分隔符(Windows 是 `,Linux/macOS 是/`) | path = os.path.join(‘folder’, ‘sub’, ‘file.txt’) |
os.path.abspath(path) | 将相对路径转换为绝对路径 | abs_path = os.path.abspath(‘./file.txt’) |
os.path.dirname(path) | 返回路径中的目录部分 | dir_part = os.path.dirname(‘/home/user/file.txt’) # ‘/home/user’ |
os.path.basename(path) | 返回路径中的文件名部分(包括扩展名) | file_part = os.path.basename(‘/home/user/file.txt’) # ‘file.txt’ |
os.path.split(path) | 将路径分割为目录和文件名两部分,返回元组 (目录, 文件名) | dir_name, file_name = os.path.split(‘/home/user/file.txt’) |
os.path.splitext(path) | 将路径分割为文件名和扩展名两部分,返回元组 (文件名, 扩展名) | name, ext = os.path.splitext(‘report.pdf’) # (‘report’, ‘.pdf’) |
os.path.exists(path) | 判断路径(文件或目录)是否存在 | if os.path.exists(‘important.txt’): … |
os.path.isfile(path) | 判断路径是否是文件 | if os.path.isfile(‘document.txt’): … |
os.path.isdir(path) | 判断路径是否是目录 | if os.path.isdir(‘images’): … |
os.path.getsize(path) | 获取文件的大小(字节) | size = os.path.getsize(‘video.mp4’) |
os.path.getmtime(path) | 获取文件的最后修改时间(返回时间戳,可用 time.ctime()转换) | mtime = os.path.getmtime(‘file.txt’) |
系统信息与操作
方法/属性 | 作用说明 | 示例 |
---|---|---|
os.name | 获取操作系统名称(Windows 是 ‘nt’,Linux/Unix/macOS 是 ‘posix’) | if os.name == ‘posix’: print(“这是类Unix系统”) |
os.sep | 获取操作系统使用的路径分隔符(Windows 是 `,Linux/macOS 是/`) | print(f"系统分隔符: {os.sep}") |
os.system(command) | 在子 shell 中执行系统命令(字符串形式),返回命令的退出状态码 | exit_code = os.system(‘ls -l’) |
os.environ | 获取系统环境变量的字典 | python_path = os.environ.get(‘PYTHONPATH’) |
os.getenv(‘KEY’) | 获取指定环境变量的值,如果不存在则返回 None | home_dir = os.getenv(‘HOME’) # 类Unix系统上为用户家目录 |
os.cpu_count() | 返回系统的 CPU 核心数量(包括逻辑核心) | cores = os.cpu_count() |
os.urandom(n) | 生成随机字节串(密码学安全),常用于生成密钥、令牌等 | random_bytes = os.urandom(16) |
实用技巧与注意事项
1. 路径拼接就用 os.path.join:它能自动处理不同操作系统的路径分隔符,避免手动拼接时忘记分隔符或使用硬编码分隔符的问题。
2. 检查存在性:在删除文件 (os.remove) 或目录 (os.rmdir) 前,最好先用 os.path.exists、os.path.isfile或 os.path.isdir检查一下,防止程序因路径不存在而崩溃。
3. 处理空格和特殊字符:os.system虽然方便,但如果命令或参数中包含空格或特殊字符(如 &, |),可能会引发意外行为。更安全、强大的替代方案是 subprocess模块。
4. 谨慎使用 os.system和 os.remove:这些操作直接影响系统,特别是执行删除或修改系统设置的命令时,务必谨慎,最好先备份重要数据或在测试环境中验证。
- 遍历目录:os.walk是深度遍历目录树的强大工具,比 os.listdir更适用于需要递归处理所有子目录的情况。
PyMuPDF 相关用法
PyMuPDF(也常通过 import fitz导入)是一个功能强大且高效的 Python 库,用于处理 PDF 和各种文档格式。
pip install pymupdf # 安装
import fitz # 导入# 1. 打开文件
doc = fitz.open("your_document.pdf") # 打开PDF文件,从内存数据打开文档,或创建新的空 PDF
print(f"页数: {doc.page_count}") # 获取文档总页数
print(f"元数据: {doc.metadata}") # 获取文档元数据(作者、标题等)[2](@ref)
doc.close() # 关闭文档:操作完成后,记得关闭文档以释放资源page = doc.load_page(0) # 加载第一页(页码从0开始)
text = page.get_text() # 提取页面文本
# get_text()方法支持多种参数(如 "blocks"、"words"、"html")以不同格式提取文本# 2. 在页面中搜索特定词
text_instances = page.search_for("搜索关键词")
for inst in text_instances:print(f"找到匹配,位置: {inst}")
# 3. 提取页面图像
image_list = page.get_images(full=True)
for img_index, img in enumerate(image_list):xref = img[0]base_image = doc.extract_image(xref)with open(f"image_{img_index}.png", "wb") as f:f.write(base_image["image"]) # 保存图像[2](@ref)# 4. 将页面渲染为图像
pix = page.get_pixmap(matrix=fitz.Matrix(2, 2)) # 2倍缩放提高清晰度
pix.save("page_image.png") # 保存为PNG文件[2](@ref)# 5. 插入文本
page = doc[0] # 获取第一页
page.insert_text((50, 50), "Hello, World!", fontname="helv", fontsize=12) # 在指定位置插入文本
doc.save("modified.pdf") # 保存修改后的文档[1](@ref)# 6. 插入图像
page.insert_image((50, 50, 200, 200), filename="image.png") # 在指定矩形区域插入图像
doc.save("with_image.pdf")[1](@ref)# 7. 旋转页面
page.set_rotation(90) # 将页面顺时针旋转90度[2](@ref)# 8. 删除、复制、移动页面
doc.delete_page(0) # 删除第一页
doc.copy_page(1) # 复制第二页
doc.move_page(2, 0) # 将第三页移动到开头[4](@ref)# 9. 合并 PDF 文档
doc1 = fitz.open("document1.pdf")
doc2 = fitz.open("document2.pdf")
doc1.insert_pdf(doc2) # 将 doc2 的所有页面插入到 doc1 末尾
doc1.save("merged_document.pdf")[1](@ref)# 10. 拆分 PDF 文档
# 提取特定页面范围到新文档
new_doc = fitz.open()
new_doc.insert_pdf(doc, from_page=0, to_page=4) # 提取前5页
new_doc.save("extracted_pages.pdf")[4](@ref)# 11. 处理加密 PDF
doc = fitz.open("encrypted.pdf", password="your_password")[2](@ref) # 打开加密的 PDF
doc.encrypt("user_password", "owner_password", # 加密保存 PDF
permissions=fitz.PDF_PERM_PRINT) # 设置密码和权限[1](@ref)# 12. 处理链接和注释
# 获取页面所有链接
links = page.get_links()
for link in links:if link["kind"] == fitz.LINK_URI:print(f"URL链接: {link['uri']}")# 获取文档书签(目录)
toc = doc.get_toc()
for item in toc:print(f"层级: {item[0]}, 标题: {item[1]}, 页码: {item[2]}")[4](@ref)