当Word文档里的图片成了“拦路虎”:用Python批量处理图片的实战指南
你有没有遇到过这样的场景部门例会前领导丢给你一个文件夹里面是几十个Word文档每个文档里都散落着好几张活动照片。你的任务很简单——把所有图片提取出来统一调整尺寸再按照特定的顺序塞进一个新的报告文档里。听起来不难对吧但当你打开第一个文档一张张右键另存为再调整尺寸再复制粘贴到新文档……重复几十次之后你会开始怀疑人生。手头的工作变成了纯粹的体力劳动而且只要有一个环节出错就得从头再来。这种时候Python就派上用场了。它不会抱怨重复劳动也不会因为眼花点错图片。我花了两个小时写了一小段脚本把原本一整天的手工活压缩成了三分钟。今天就把这段经历和代码拆开来讲希望能帮你摆脱同样的困境。准备工作装好工具箱在动手之前得先把需要用到的工具装上。Python的好处就是有大量的第三方库专门解决这类问题。这次我们需要三个帮手pip install python-docx pillowpython-docx是我们操作Word文档的主力。它可以读取文档里的文字、表格、图片也能从头创建新的文档或者修改现有的文档。Pillow是Python图像处理库负责调整图片尺寸、转换格式这些活儿。安装完成之后在代码开头把这些库引进来from docx import Document from docx.shared import Inches, Cm from PIL import Image import io import osInches和Cm是用来设置图片大小的单位io帮我们处理内存里的图片数据os负责管理文件和文件夹路径。从Word文档里“捞”出图片Word文档和图片的关系比看起来要复杂一点。你可能会想图片不就是放在文档里的吗但当我们用代码去读取时需要找到正确的“门路”。每个.docx文件其实是个压缩包图片被藏在内部的media文件夹里通过XML关系与文档内容关联。python-docx提供了一个方法可以顺着这个关系把图片提取出来。下面这段代码能遍历一个文件夹里所有的Word文档把每张图片提取出来按照“文档名_图片序号.jpg”的格式保存def extract_images_from_docx(folder_path): # 遍历文件夹里所有docx文件 for filename in os.listdir(folder_path): if not filename.endswith(.docx): continue doc_path os.path.join(folder_path, filename) doc Document(doc_path) # 准备一个文件夹存放提取出的图片 img_folder os.path.join(folder_path, filename.replace(.docx, _images)) if not os.path.exists(img_folder): os.makedirs(img_folder) img_count 0 # 遍历文档中的所有段落 for paragraph in doc.paragraphs: for run in paragraph.runs: # 在run的XML中查找图片标记 blip run._r.find(.//a:blip, namespaces{a: http://schemas.openxmlformats.org/drawingml/2006/main}) if blip is not None: embed_id blip.get({http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed) if embed_id and embed_id in run.part.related_parts: image_part run.part.related_parts[embed_id] img_stream io.BytesIO(image_part.blob) img Image.open(img_stream) img_count 1 img_path os.path.join(img_folder, fimage_{img_count}.jpg) img.save(img_path, JPEG) print(f已提取: {img_path}) print(f{filename} 处理完成共提取 {img_count} 张图片)这段代码的核心是那个看起来很复杂的XML查找。简单解释一下Word文档的内部结构是用XML描述的图片会被标记为a:blip元素通过embed属性关联到实际的图片数据。我们把图片数据从内存里读出来用Pillow打开再保存到本地就完成了提取。批量处理图片统一尺寸和格式提取出来的图片可能大小不一有的横版有的竖版如果直接塞进文档里会很难看。我们可以统一调整尺寸让它们都变成一样的宽度高度按比例自动缩放。def resize_images(image_folder, output_width500): # 获取文件夹里所有图片 image_files [f for f in os.listdir(image_folder) if f.endswith((.jpg, .jpeg, .png))] for img_file in image_files: img_path os.path.join(image_folder, img_file) img Image.open(img_path) # 计算等比例缩放后的高度 original_width, original_height img.size new_height int(output_width * original_height / original_width) # 使用高质量缩放算法 resized_img img.resize((output_width, new_height), Image.Resampling.LANCZOS) # 覆盖原图或者保存为新文件 resized_img.save(img_path, quality95) print(f已调整尺寸: {img_file} - {output_width}x{new_height})这里用了Image.Resampling.LANCZOS这是Pillow里质量最高的缩放算法虽然慢一点但效果最好。如果你的图片数量特别多可以考虑用Image.Resampling.BILINEAR换速度。把图片塞回新文档图片都准备好了现在要把它们按照顺序插进一个新的Word文档里。python-docx插入图片的方法很直观用add_picture就行def create_photo_report(image_folder, output_pathreport.docx): # 创建新文档 doc Document() # 添加标题 doc.add_heading(活动照片集锦, 0) # 获取所有图片文件并排序 image_files sorted([f for f in os.listdir(image_folder) if f.endswith((.jpg, .jpeg, .png))]) for img_file in image_files: img_path os.path.join(image_folder, img_file) # 添加一个段落放图片说明 doc.add_heading(img_file.replace(_, ).replace(.jpg, ), level2) # 插入图片宽度设为6英寸高度自动缩放 doc.add_picture(img_path, widthInches(6)) # 添加一点留白 doc.add_paragraph() doc.save(output_path) print(f报告已生成: {output_path})add_picture的width参数可以接受Inches、Cm或Pt单位。如果你想让图片按固定高度插入也可以用height参数。只指定一个维度时另一个维度会自动等比缩放不用自己算。进阶技巧在指定位置插入图片有些时候光是把图片堆在文档末尾不够用。你可能需要把图片插到某个段落后边或者放到表格的某个单元格里。在段落里插图片关键是先拿到那个段落然后在它的run里添加# 假设我们要在文档的第一个段落之后插入图片 doc Document(existing.docx) target_paragraph doc.paragraphs[0] # 获取第一个段落 run target_paragraph.add_run() # 在段落中创建一个新run run.add_picture(image.jpg, widthInches(3)) # 插入图片在表格里插图片也类似先定位到单元格再操作table doc.add_table(rows2, cols2) cell table.cell(0, 0) # 第一行第一列 paragraph cell.paragraphs[0] run paragraph.add_run() run.add_picture(image.jpg, widthCm(5))需要注意的是python-docx对图片位置的精确控制能力有限没办法像手动操作那样任意拖拽到指定坐标。如果对排版有很高要求可以先通过代码把图片插入到位再用Word手动微调。处理那些烦人的“坑”实际应用中总会遇到一些意外情况比如文档里有浮动图片、文档是旧的.doc格式等等。这里说几个常见坑的应对方法。浮动图片提取不到上面那种通过段落查找的方法只能提取“嵌入型”图片。如果文档里有浮在文字上方的图片需要更底层的操作。可以用python-docx的part.related_parts遍历所有资源找到图片类型就保存。一个更简单但笨一点的办法是先把文档另存为.docx用压缩软件打开直接去word/media文件夹里复制图片。遇到.doc格式python-docx只支持.docx处理不了旧版.doc文件。可以先用win32com库在Windows上转换或者用LibreOffice的命令行工具批量转换。如果只是偶尔遇到手动转一下可能更快。图片插入后变形这通常是因为给图片设置了固定的宽高但比例和原图不一致。解决办法是只设置一个维度让另一个维度自动缩放。如果必须指定两个维度可以先用Pillow读取原图尺寸再手动计算缩放后的宽高。写在最后回到开头的场景当你再次面对几十个需要处理图片的Word文档时你可以选择继续手工操作也可以写一段脚本然后去泡杯咖啡等着它帮你把一切做完。Python自动化最大的魅力就在这里——它不是为了炫技而是为了把我们从重复劳动里解放出来去做那些真正需要思考和创造的事情。这次我们只用了python-docx和Pillow两个库但你能做的事情远不止提取和插入图片。想想你日常工作里那些“反复做、费时间、有规律”的事情很可能都可以用类似的方式自动化。批量生成合同、整理数据报表、统一修改文档格式……这些场景里Python都能成为你的得力助手。