【Python】批量导出word文档中的图片、嵌入式文件
Python 批量导出word文档中的图片、嵌入式文件
需求
学生试卷中的题目有要提交截图的,也有要提交文件的,为了方便学生考试,允许单独交或者嵌入Word中提交,那么事后如何整理学生的答案?单独提交的比较方便,直接扫描文件名匹配名字后放入指定文件夹即可。但是嵌入到Word中的图片和文件怎么提取出来呢?
现有如下需求:提取出一个Word文档中所有的图片(png、jpg)和嵌入的文件(任意格式)放入到指定的文件夹。
解决
docx是一个压缩包,解压缩后图片一般都放在文档名.docx\word\media\
目录下:
而嵌入式文件一般都放在文档名.docx\word\embeddings\
目录下:
经过询问度娘,发现提取图片比较简单,直接使用docx
库中的Document.part.rels{k:v.target_ref}
找到文件的相对路径,用Document.part.rels{k:v.target_part.blob}
读出文件内容。简单判断一下路径和文件后缀是不是我们需要的media下的png文件和embeddings下的bin文件,是的话写入到新文件中即可:
提取图片
安装python-docx库
pip install python-docx
提取
import osfrom docx import Document # pip install python-docxis_debug = Trueif __name__ == '__main__':# 需要导出的Word文档路径target_file = r'paper\HBase试题.docx'# 导出文件所在目录output_dir = r'paper\output'# 加载Word文档doc = Document(target_file)# 遍历Word包中的所有文件dict_rel = doc.part.rels# r_id:文件身份码,rel:文件对象for r_id, rel in dict_rel.items():if not ( # 如果文件不是在media或者embeddings中的,直接跳过str(rel.target_ref).startswith('media')or str(rel.target_ref).startswith('embeddings')):continue# 如果文件不是我们想要的后缀,也直接跳过file_suffix = str(rel.target_ref).split('.')[-1:][0]if file_suffix.lower() not in ['png', 'jpg', 'bin']:continue# 如果输出目录不存在,创建if not os.path.exists(output_dir):os.makedirs(output_dir)# 构建导出文件的名字和路径file_name = r_id + '_' + str(rel.target_ref).replace('/', '_')file_path = os.path.join(output_dir,file_name)# 将二进制数据写入到新位置的文件中with open(file_path, "wb") as f:f.write(rel.target_part.blob)# 打印结果if is_debug:print('导出文件成功:', file_name)
运行结果:
可以看到,图片都能正常导出,但是学生嵌入的JAVA文件并没有导出,或者说导出的是bin文件,没有完全导出。
提取嵌入式文件
再次询问度娘发现,这种其实也是zip压缩包,但是不能直接提取出,它有个更专业的名字,叫ole文件,我们之前的doc、xls、ppt等没有带x的上古文档文件都是这种格式。那如何提取出文件呢?度娘告诉我有个叫oletools的项目可以,于是下载下来浅浅地分析了下,发现确实可以!
oletools项目地址:https://github.com/decalage2/oletools
或者gitee上别人转存的地址:https://gitee.com/yunqimg/oletools
我是用的gitee上的版本,因为github打不开 QwQ
经相关文档介绍,项目下的oletools-master\oletools\oleobj.py
就可以提取这种bin后缀的ole文件,简单试一下,在oleobj.py所在目录下打开命令行,把刚刚提取出的rId12_embeddings_oleObject1.bin文件复制到oleobj.py所在目录,执行如下命令:
注意: 在此之前我执行了一下安装oletools的命令,如果不安装可能会出错:pip install oletools
,或者说oleobj.py依赖olefile:pip install olefile
,在安装oletools时顺便安装了olefile。
python oleobj.py rId12_embeddings_oleObject1.bin
成功导出
Microsoft Windows [版本 10.0.22000.708]
(c) Microsoft Corporation。保留所有权利。D:\Minuy\Downloads\oletools-master\oletools-master\oletools>python oleobj.py rId12_embeddings_oleObject1.bin
oleobj 0.56 - http://decalage.info/oletools
THIS IS WORK IN PROGRESS - Check updates regularly!
Please report any issue at https://github.com/decalage2/oletools/issues-------------------------------------------------------------------------------
File: 'rId12_embeddings_oleObject1.bin'
extract file embedded in OLE object from stream '\x01Ole10Native':
Parsing OLE Package
Filename = "Boos.java"
Source path = "D:\111\´ó20´óÊý¾Ý Àî¾üÁé\Boos.java"
Temp path = "C:\Users\ADMINI~1\AppData\Local\Temp\Boos.java"
saving to file rId12_embeddings_oleObject1.bin_Boos.javaD:\Minuy\Downloads\oletools-master\oletools-master\oletools>
导出的文件也能正常访问:
于是把oletools目录复制到工程项目下,稍微修改一下oleobj.py能让我的代码调用它,在oleobj.py中添加如下代码:
def export_main(ole_files, output_dir, log_leve=DEFAULT_LOG_LEVEL):ensure_stdout_handles_unicode()logging.basicConfig(level=LOG_LEVELS[log_leve], stream=sys.stdout,format='%(levelname)-8s %(message)s')# 启用日志模块log.setLevel(logging.NOTSET)any_err_stream = Falseany_err_dumping = Falseany_did_dump = Falsefor container, filename, data \in xglob.iter_files(ole_files,recursive=False,zip_password=None,zip_fname='*'):if container and filename.endswith('/'):continue# 输出文件夹err_stream, err_dumping, did_dump = \process_file(filename, data, output_dir)any_err_stream |= err_streamany_err_dumping |= err_dumpingany_did_dump |= did_dumpreturn_val = RETURN_NO_DUMPif any_did_dump:return_val += RETURN_DID_DUMPif any_err_stream:return_val += RETURN_ERR_STREAMif any_err_dumping:return_val += RETURN_ERR_DUMPreturn return_valdef export_ole_file(ole_files, output_dir, debug=False):debug_leve = 'critical'if debug:debug_leve = 'info'# 导出result = export_main(ole_files,output_dir,debug_leve)if result and debug:print('导出ole文件出错', ole_files)
在提取文件的代码后面加上如下调用:
if str(rel.target_ref).startswith('embeddings'):# 解压嵌入式文件export_ole_file([file_path], output_dir)
再次运行
成功导出嵌入到Word中的文件!
成功解决问题~
资源
oletools:https://gitee.com/yunqimg/oletools
本项目:https://gitcode.net/XiaoYuHaoAiMin/export_docx_media_file
本项目打包:https://download.csdn.net/download/XiaoYuHaoAiMin/85643779
参考文档
https://blog.csdn.net/culun797375/article/details/108840682 (手动提取)
https://github.com/decalage2/oletools (本次主角之一oletools的仓库)
https://gitee.com/yunqimg/oletools (oletools在gitee上的副本)
https://blog.csdn.net/u011420268/article/details/106402153 (插入附件,想参考其普通文件如何转ole的,但是好像没转ole格式)
https://blog.csdn.net/lly1122334/article/details/109669667 (python-docx的使用)
https://zhuanlan.zhihu.com/p/446557096(oletools教程)
https://blog.csdn.net/tixxxa/article/details/120429483 (导出附件Python实现,没用oletools,好像不行,有兴趣的同志可以研究下)
https://blog.csdn.net/Cody_Ren/article/details/103886098 (ole文件结构,发现oletools后放弃自己写了)
https://blog.csdn.net/m0_60574457/article/details/119279798 (oletools中文教程,好像是readme.md翻译过来的)
【Python】批量导出word文档中的图片、嵌入式文件相关推荐
- python批量提取word文档中的图片(含图片格式转换和GUI)
作者:小小明 文章目录 doc格式批量转为docx 批量提取docx文档的图片 批量图片格式转换 完整代码 GUI图形化工具开发 打包exe 给GUI加入进度条 日常工作中,领导要求你将一份 Word ...
- 使用Python批量提取Word文档中的图片
1.导入需要的包 import zipfile import shuti 2.设置文档路径和图片路径 ,并用zipfile读取Word文件 doc_path = './a.docx' #在这里更换你想 ...
- 办公室小姐姐的福利!用Python批量提取word文档中的表格和图片内容
点上方"菜鸟学Python",选择"星标" 第491篇原创干货,第一时间送达 最近有许多小伙伴想要一些自动化办公的福利小程序,今天就满足大家的需求.日常的办公过 ...
- ChatGPT搞砸了~,如何使用VBA导出Word文档中的图片
今年大火的ChatGPT似乎无所不能,但是它的确不是万能的,咱们来试试. 提供的代码根本无法运行,继续问,换了个代码,非常不幸的是–还是不能用. Word VBA中并没有内置的方法可以直接导出图片,C ...
- Python批量修改Word文档中特定关键字的颜色
关于Word文件的大致结构请参考使用Python写入docx文件并控制字体颜色 代码功能:读取docx文档中的文字,在尽量不影响原来字体样式的情况下,只把特定的文字都修改为红色. 表格中的文字请参考P ...
- 通过VBA导出word文档中的图片
一.问题重述: 工作中,经常有同事把新闻的照片贴在word文档中发过来,需要把照片一张张的转存成图片. 二.原始方法: 在文档中的照片上,右键,图片另存为-- 把文档,按F12,另存为网页文件,然后在 ...
- 5导出word_妙招技法 | 教你如何快速导出Word文档中的图片
关注[新精英充电站]能力提升看得见! 我们在翻阅一些比较好的Word文档时,经常想要将文档中用到的一些好的图片素材保留下来,但却苦于不知道怎么保存,最后只有无奈放弃. 其实,Word中提供有导出图片的 ...
- java poi在word文档中插入图片后文件无法打开
错误情况 POI生成的word文档包含图片时用office打开失败,提示错误.但是用wps却可以打开. 原因分析 这是因为poi本身的问题,单纯的插入图片是不显示的,可以使用如下处理方式createP ...
- 怎么样才可批量导出word文档中的照片 不再一张一张的另存为!
再也不用一个一个的另存为啦. 果然,重复的操作都可以用计算机来解决! 点击另存为,格式选为HTML. 可以直接保存到桌面. 点击保存之后: (图片内容不是重点.) 原来的.doc文件就变成了.html ...
最新文章
- elasticsearch 安装
- 你应该使用Java8 非阻塞异步API来优化你的系统了
- 树莓派应用实例3:环境光照强度测量
- 拍照时不会摆Pose怎么办?
- 那些 Linux 下好用的 小工具 收集
- 「禾连健康」轻松实现弹性降本20%以上,竟然是因为使用了它!
- Python 3.5.2 TypeError: a bytes-like object is required, not 'str’问题解决方案
- java实参将数据传递给形参的两种形式
- 一个简简单单检测http服务状态的脚本
- 自动生成getter,setter方法的插件lombok
- CF724G. Xor-matic Number of the Graph
- 应用百花齐放,呈现北浙苏沪粤五极格局丨2021年中国区块链产业发展报告产业应用篇...
- CC2530单片机开发--串口
- 阿里云国际版账户登录不上去什么原因?
- sir模型初始值_SIR模型简单了解(Susceptible Infected Recovered Model)
- vim 安装YouCompleteMe 插件
- c++ 线程进度条_AMD R9 5900X 跑分曝光,单线程性能大幅提升;天猫“官宣”苹果iPhone 12:暗示10月16日开启预定...
- obs直播软件 android,斗鱼游戏直播教程-OBS直播软件篇
- Linux虚拟机的远程三种链接,以及各自的上网方式
- 码刀客-pandas中将一张表中数据拆分成多个sheet_name
热门文章
- BERT通俗笔记:从Word2Vec/Transformer逐步理解到BERT
- oracle缓冲区闩锁类型,等待缓冲区闩锁时出现超时 -- 类型 4
- js中使用btoa和atob进行Base64的编码和解码
- 医学影像工作站程序ProDicom的说明
- php如何开发调色器,HTML5+Js制作的一款简易调色器
- uefi装完系统后无法引导_uefi模式怎么重装系统|uefi重装系统教程
- 音标、音节、音素、音符
- C语言中的找特殊数字问题
- 从人人网“死亡”看“级联”效应
- 堆晶结构_堆晶岩形成条件