如何提取.docx文件中出现2次及以上的重复图片?
这个需求确实有点 tricky,毕竟默认的工具都是帮你自动去重,而你要的反而是留下那些出现至少两次的图片。我刚好有个可行的方案,用 Python 结合 python-docx 和 zipfile 就能实现,下面一步步给你讲清楚:
核心思路
DOCX 文件本质是个压缩包,里面的图片都存在 word/media/ 目录下,每个图片会通过一个唯一的关系 ID(rId)和文档内容关联。我们需要:
- 遍历文档内容,统计每个 rId 对应的图片被引用的次数
- 筛选出引用次数 ≥2 的 rId,然后从压缩包中提取对应的图片文件
具体实现代码
首先安装依赖库:
pip install python-docx
然后运行下面的脚本:
import docx import zipfile import os import shutil import xml.etree.ElementTree as ET def extract_duplicate_images(docx_path, output_folder): # 创建输出文件夹(不存在则自动创建) os.makedirs(output_folder, exist_ok=True) # 第一步:统计每个图片的引用次数 doc = docx.Document(docx_path) image_reference_counts = {} # 遍历所有段落中的图片 for paragraph in doc.paragraphs: for run in paragraph.runs: # 通过 XPath 定位图片元素 pic_elements = run._element.xpath('.//pic:pic') if pic_elements: # 获取图片对应的关系 ID(rId) r_id = run._element.xpath('.//a:blip/@r:embed')[0] # 更新计数 image_reference_counts[r_id] = image_reference_counts.get(r_id, 0) + 1 # 筛选出引用次数≥2的图片rId duplicate_image_rids = [rid for rid, count in image_reference_counts.items() if count >= 2] if not duplicate_image_rids: print("文档中没有找到重复出现的图片") return # 第二步:从DOCX压缩包中提取目标图片 with zipfile.ZipFile(docx_path, 'r') as zip_ref: # 读取关系映射文件,关联rId和实际图片路径 rels_content = zip_ref.read('word/_rels/document.xml.rels').decode('utf-8') ns = {'r': 'http://schemas.openxmlformats.org/package/2006/relationships'} root = ET.fromstring(rels_content) rid_to_media_path = {} for rel in root.findall('r:Relationship', ns): rel_id = rel.get('Id') target_path = rel.get('Target') if target_path.startswith('media/'): rid_to_media_path[rel_id] = f'word/{target_path}' # 复制符合条件的图片到输出文件夹 for rid in duplicate_image_rids: media_path = rid_to_media_path.get(rid) if media_path and media_path in zip_ref.namelist(): filename = os.path.basename(media_path) # 提取并保存图片 with zip_ref.open(media_path) as source_file, open(os.path.join(output_folder, filename), 'wb') as dest_file: shutil.copyfileobj(source_file, dest_file) print(f"已提取重复图片:{filename}") # 调用函数,替换成你的文件路径和输出文件夹 extract_duplicate_images( r"C:\Users\name\Documents\document_with_image.docx", r"C:\Users\name\Documents\duplicate_images" )
代码说明
- 统计引用次数:通过
python-docx遍历文档的段落和运行块,用 XPath 定位图片元素,获取对应的 rId 并计数 - 关联rId与图片路径:DOCX 的
word/_rels/document.xml.rels文件存储了 rId 和实际媒体文件的映射关系,我们解析这个文件来找到每个 rId 对应的图片位置 - 提取目标图片:从压缩包中读取符合条件的图片文件,复制到指定输出文件夹
补充说明
如果你的文档里有图片在文本框、表格单元格等特殊容器中,上面的代码可能无法完全覆盖,这时候可以额外遍历文档中的形状元素(doc.inline_shapes 和 doc.shapes)来补充统计,不过大部分常规场景下,上面的代码已经够用了。
内容的提问来源于stack exchange,提问作者sush




