背景

在互联网教育行业,做内容相关的项目经常碰到的一个问题就是如何解析word文档。

因为系统如果无法智能的解析word,那么就只能通过其他方式手动录入word内容,效率低下,而且人工成本和录入出错率都较高。


疑难点

word解析可以预见的困难主要有以下几个方面:

  • word 结构问题 —— word不开源,且含有很多非文本内容,比如图表,而已知的常规方法只能解析纯文本内容,所以如果不知道word内部层级结构,解析将难以进行。
  • word 公式问题 —— word公式来源并非单一,可能是用MathType插件生成的latex公式,也可能是用word自带公式编辑器生成的公式,还有可能公式部分手敲,部分使用搜狗输入法或者其它编辑器输入。不同来源处理方式是否一样?且能否有效读取文档各种上下脚标?方便后期展示?
  • word 非文本问题 —— word含有很多的非文本内容,比如图表。来源也多样,图表可能是用word自带的画图工具生成的,也有可能是复制粘贴的,不同来源解析方式是否一样?且读取的时候是否能有效获取图片的位置及大小信息?方便文档内容后期在PC端和移动端展示。无论最终方案是什么,肯定是将所有的且需要的非文本信息转换为文本信息。
  • word 版本问题 —— word有03、07等好几个版本,还有WPS版本,解析是否要全部兼容?后缀名有docx和doc,是否全部兼容?当然,前提是已经成功解析一种类型。
  • word 规范问题 —— 有些word可能是早期制作的,返工代价太大,所以格式内容多样化。而且就算制定word格式规范,新制作的word也无法保证格式一定正确,除非是程序自动生成的文档。举个例子,试题的题序,肉眼无法区分的格式就有好几种。程序只可能尽量覆盖绝大部分情况,考虑的情况越多,解析正确率越高,当然程序也更复杂。


Java解析word

以前曾用Java解析过word文档,所以最先考虑用Java来解决问题,网上搜索方案主要有如下几种:

  • jacob:网上资料较少,目前已经实现的是用jacob解析mathtype输入的公式,然后调用word宏命令转成latex,但jacob无法解析word自带的公式。jacob也可以定位word图片总数及word图片位置,但目前没找到将图片另存本地的方法。
  • poi:情况与jacob类似。
  • Aspose.words:一个商业收费类库,可以使应用程序处理大量的文件任务,支持word、pdf等各种格式操作。但是看文档介绍没有关于公式的处理方案。

Java使用以上几种方案的确解决了部分问题,但很多异常情况还是无法处理,比如无法定位word的批注等。

以下是使用Java定位word图片总数及其位置的代码,更多解决方案请戳 http://www.cnblogs.com/x_wukong/p/4270867.html

package com.latex.test;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant; public class test {
public static void main(String[] args) {
long time1 = System.currentTimeMillis();
ActiveXComponent word = new ActiveXComponent("word.Application");
Dispatch wordObject = (Dispatch) word.getObject();
Dispatch.put((Dispatch) wordObject, "Visible", new Variant(false));
Dispatch documents = word.getProperty("Documents").toDispatch();
Dispatch document = Dispatch.call(documents, "Open", "D://test.docx").toDispatch();
Dispatch wordContent = Dispatch.get(document, "Content").toDispatch();
Dispatch paragraphs = Dispatch.get(wordContent, "Paragraphs").toDispatch(); int paragraphCount = Dispatch.get(paragraphs, "Count").getInt();// 总行数
for (int i = 1; i <= paragraphCount; i++) {
Dispatch paragraph = Dispatch.call(paragraphs, "Item", new Variant(i)).toDispatch();
Dispatch paragraphRange = Dispatch.get(paragraph, "Range").toDispatch();
String paragraphContent = Dispatch.get(paragraphRange, "Text").toString();
System.out.println(paragraphContent);//打印每行内容 Dispatch imgDispatch = Dispatch.get(paragraphRange, "InlineShapes").toDispatch();//图片
int imgCount = Dispatch.get(imgDispatch, "Count").getInt();
System.out.println("第" + i +"行图片总数" + imgCount); for(int j=1;j<imgCount+1;j++){
Dispatch shape = Dispatch.call(imgDispatch, "Item", new Variant(1)).toDispatch();
Dispatch imageRange = Dispatch.get(shape, "Range").toDispatch();
Dispatch.call(imageRange, "Copy");
Dispatch.call(imageRange, "Paste");
}
} Dispatch.call(document, "SaveAs" , new Variant( "D://test1.docx"));
Dispatch.call(document, "Close", new Variant(true));
Dispatch.call(word, "Quit");
long time2 = System.currentTimeMillis();
double time3 = (time2 - time1)/1000;
System.out.println(time3 + " 秒."); }
}

问题分析

用Java预研一段时间后,进展缓慢,很多非文本内容无法解析,归根结底是不知道word内部层级结构。

如果能像html页面那样知道各个节点的构成,那么word解析成功按道理就只是时间问题。

但是word是微软的项目,不开源,所以得去搜索下微软本身是否提供了解析word层级结构的插件。

然后发现了个好东东,名为 Open XML SDK 2.0 Productivity Tool

下载安装后,把一个word文档拖进面板,就可以看见word层级结构了 ~(~ ̄▽ ̄)~

知道层级结构就可以着手解决解析问题了,其它核心细节这里不方便透露,感兴趣的可以私聊,哈哈 ~~


其他

word中的公式处理是一个比较大的门槛,这里分享一篇不错的文章:

菁优网、梯子网、猿题库的数学公式是如何实现的?

最新文章

  1. ubuntu 12.04 LTS 如何使用更快的更新源
  2. iscroll 加载不全解决方案
  3. Android基础:Activity
  4. 《Java编程那点事儿》读书笔记(六)——异常处理
  5. mysql表的一对一/一对多/多对多联系
  6. HttpClient(4.3.5) - HTTP Request &amp; HTTP Response
  7. URAL 1260 Nudnik Photographer(递推)
  8. 应用引擎BAE3.0介绍及百度BAE3.0支持并发多少
  9. Sudoku(回溯)
  10. C++編程札記「基礎」
  11. iOS开发——判断是否第一次启动
  12. TP5常用命令符操作
  13. swift之函数式编程(四)
  14. linux 下启动java jar包 shell
  15. IntelliJ IDEA 2018.3 重大升级,哪些功能打动了你?
  16. shell脚本编写某一文件夹内拷贝某一段文件(有则跳过没有则拷贝)
  17. vue 关于vue.set的学习笔记
  18. python学习笔记02--列表和元组
  19. 廖雪峰Java3异常处理-1错误处理-3抛出异常
  20. asp.net MVC中防止跨站请求攻击(CSRF)的ajax用法

热门文章

  1. PopupWindow 使用
  2. MarkdownPad2.5 注册码
  3. 【转】ORACLE定期清理INACTIVE会话
  4. 手把手教你用python打造网易公开课视频下载软件1-总述
  5. 爱上MVC~AuthorizeAttribute验证不通过如何停止当前上下文
  6. docker nginx1.7.6+keepalived实现双机热备
  7. windows phone 7 中怎样定义和使用资源(Resource)
  8. Redis Sentinel高可用配置及C#访问
  9. 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)
  10. cocos2d-x 详解之 CCTexture2D(纹理图片)和 CCTextureCache(纹理缓存)
  11. 第四篇:python基础之dict、set及字符
  12. c++基础五个题(三)
  13. ${pageContext.request.contextPath}的作用
  14. Android WebView 上传各种文件(包括拍照 录像 录音 文件 音乐 等,用到图片或拍照的,可以参考下)
  15. BZOJ4828 AHOI/HNOI2017大佬(动态规划+bfs)
  16. webstorm显示行号,结构预览
  17. 更优雅地关闭资源 - try-with-resource及其异常抑制
  18. Alpha预乘-混合与不混合[转]
  19. valgrind使用指南
  20. epoll实现机制分析