liyongsea / parallel_corpus_mnbvc

parallel corpus dataset from the mnbvc project
Apache License 2.0
7 stars 5 forks source link

doc -> docx #54

Closed voidf closed 4 months ago

voidf commented 10 months ago

说一下这个分支都做了什么:由于doc是非开源格式,为了保证转换质量,这里采用python走pywin32调用Microsoft Office中的WORD来打开doc文件、另存为格式开源的docx的方式来进行转换。

经过探索,多进程地打开doc并且另存为docx并不能提高转换效率,直接多开WORD也不行,windows server的单(和多)用户多会话层面并行做也不行,怀疑是WINWORD.EXE它自己有一个大锁令打开和另存为这个操作变成串行。无奈,单机强行做并行只能考虑安装虚拟机。

由于WORD会弹出大量奇怪的拍脸弹窗阻塞整个进程,我先是引入超时机制来滤掉这些文件,但之后处理错误时发现文件太多(1.5w),人点不过来,于是引入pywinauto来做部分窗口的自动通过。

关于部署

实际地说,我在日常用的windows server 2019上单开了doc2docx_ver2.py脚本做本地处理,然后另开了一个task_server.py来做任务分发。然后本地直接使用windows自带的hyper-v功能装了7个虚拟机,每个虚拟机里跑着pywinauto_client.py来向宿主机接任务。每台节点有一个独立的32位的Office 2019,效率大概是宿主机1秒1个文件,虚拟机2秒一个文件。每台虚拟机配额是1核,4G内存(实际上3G就够了)并且打开动态内存开关。此外还在笔电本地开了一个节点,并且另外装了4个同样配置的虚拟机。

这些虚拟机最好部署在ramdisk或固态硬盘里,部署在固态中需要注意散热,有些固态过热会断开,导致数据火葬场。

脚本文件说明

  1. doc2docx.py和doc2docx_netdrive.py分别是初代和二代脚本(特判了在windows网络共享文件夹里执行的case),是老版本脚本,效率不如三代,可以考虑移除。
  2. doc2docx_ver2.py是三代脚本,是本地进行的,我能想到的写法中速度最快的脚本。它首先指定一个for循环的from,to,step(我们一共有166779个文件夹的任务),缓存WORD单例,然后用它来后台打开一个doc文件做转换。当这个过程挂起太久时,把所有WINWORD.EXE进程杀掉,然后跳过当前文件并且在err目录中打一个与当前文件同名的空log文件作为标记以便重启时跳过它们。注意它没有做拍脸弹窗的自动点击确定
  3. task_server.py是任务分发脚本,它缓存本地每个尚未处理的doc文件(它拆任务的粒度比doc2docx_ver2.py更细一级,它是按单个doc文件,而不是一份多语种文件的文件夹),把它们作为子任务通过http分给子节点做。避免每个子节点都需要全量的数据才能执行任务。实测这种方式比起网络共享文件夹要快得多。
  4. task_client.py是初代接任务的子节点执行的脚本,它与task_server.py通信来领取任务,异常处理流程和ver2相似,鲁棒性不强,一个自动修复的拍脸弹窗就能把他卡死。
  5. pywinauto_client.py是目前推荐的客户端脚本,它在task_client的基础上引入了几个常见拍脸弹窗的自动处理,即【安全模式中启动】【是否仍要打开它】【显示修复】的自动处理。