【问题标题】:Modify Apache Tika parsing of ODF and old (1997-2003) MS Word docs?修改 ODF 和旧 (1997-2003) MS Word 文档的 Apache Tika 解析?
【发布时间】:2017-06-21 05:41:57
【问题描述】:

我正在开发一个应用程序,它将对不同格式的大文件进行 Lucene 索引(将它们分成多个 org.apache.lucene.document.Documents)。至少在最初的方法中,每个“Lucene 文档”都由一个“段落”组成。

作为一般规则,Apache Tika 似乎是天赐之物:您只需向它扔一个文档,它似乎会吸出所有格式的文本。

但我想详细了解它如何处理更棘手的方面,并且在我第一次查看它如何处理脚注和尾注的过程中,我发现在 .docx 文件中它会给出这个“行",对于有 3 个脚注的行:

|Tecum optime[footnoteRef:2], deinde etiam[footnoteRef:3] cum mediocri amico[footnoteRef:4]. 
[2: Sed quoniam et advesperascit et mihi ad villam revertendum est, nunc quidem hactenus; 
Quod si ita sit, cur opera philosophiae sit danda nescio.] [3: Si quae forte-possumus. 
Immo videri fortasse.] [4: Huius ego nunc auctoritatem [sequens idem faciam]. Confecta 
res esset. Primum Theophrasti, Strato, physicum se voluit; Ut proverbia non nulla veriora 
sint quam vestra dogmata.]|

(注意,为清楚起见,我的代码添加了“|”字符)

... .doc 格式的相同文件 Tika 为您提供多个“行”:

|Tecum optime|
|, deinde etiam|
| cum mediocri amico|
|.|
...

|??|
| ? Sed quoniam et advesperascit et mihi ad villam revertendum est, nunc quidem 
hactenus; Quod si ita sit, cur opera philosophiae sit danda nescio. |
|??|
| ? Si quae forte-possumus. Immo videri fortasse. |
|??|
| ? Huius ego nunc auctoritatem [sequens idem faciam]. Confecta res esset. Primum 
Theophrasti, Strato, physicum se voluit; Ut proverbia non nulla veriora sint quam 
vestra dogmata. |

...它不仅将原始“段落”分成几行,在每个脚注引用处中断,而且还将所有脚注推到处理的末尾。

通过 .docx 文件处理,您可以提取脚注并轻松地将它们链接到它们所属的句子。 .doc 处理的工作方式当然对我的索引目的毫无帮助。事实上,我真的看不出有什么方法可以将最初产生的 4“行”识别为真正属于同一个段落。

也许可以预料,Tika 对 .doc 等过时格式的处理并不是那么美妙。我现在打算看看这里涉及的实际源代码,假设我可以在 Gradle 下载的许多源 jar 中找到它,但不是调整代码,而是有一种更“传统”的方式来修改 Tika 的解析给定格式?我做了一些搜索,但一无所获。

当然,另一种方法可能是将 .doc 文件(和 .odt 文件,见下文)“即时”转换为 .docx 以获得更高质量的解析。

PS 解析 LibreOffice .odt 文件(开放文档格式,ODF),一种非过时的格式,同样存在问题。 特别是,包含脚注/尾注的行类似地被拆分为多个行。

【问题讨论】:

标签: java parsing ms-word lucene apache-tika


【解决方案1】:

几天后我的发现供任何感兴趣的人参考。

首先,Apache 人员似乎并不真的打算让您摆弄 Tika 类。

当尝试调整 MS Word 97-2003 格式(又名 .doc)的处理时,这里涉及的主要类是 HWPFDocument(“可怕的文字处理格式”)。 Apache POI 项目的一部分,与 Tika 捆绑在一起。

此类通常会从 .doc 文件中获取InputStream,并且似乎将文件的不同元素拆分得相当无益,因此脚注等似乎与文本分开存储。 HWPFDocumentfinal,这只是问题的开始:这里的许多文件依赖于包或子包中的其他类,其中许多是final 或不是public(或@987654328 @)。我得出的结论是,我基本上必须克隆整个org.apache.poi.hwpf 包,修改它并再次打包它。我不能被打扰。

.odt (ODF) 文件类型 最终对我来说确实更重要:非过时且非 Micro$oft。这里的关键类原来是org.apache.tika.parser.odf.OpenDocumentContentParser。这里的问题是它包含一个名为OpenDocumentElementMappingContentHandler 的内部类OpenDocumentElementMappingContentHandler(即,他们真的不希望您将其子类化,甚至出于某种原因使用它的实例!) ,最终,org.xml.sax.ContentHandler。这里涉及数百个(嗯,很多)ContentHandler-实现类,其中许多是“装饰器”。但最终你需要做的是复制这个类的整个代码OpenDocumentContentParser,然后搞乱内部类。我这样做是为了在startElementendElement,根据参数qName 的值,它切换到或退出可能值“未定义”“NOTE_CITATION”或“NODE BODY”的“解析模式” " ...并在此模式设置的基础上可以取消通话

super.endElement(namespaceURI, localName, qName);

endElement。正是这个super 调用似乎触发了一个字符串的结尾和下一个字符串的开头。要将脚注编号或正文开始/结束的文本指示放在输出文本中,您可以创建 String injectedText 然后去

super.characters( injectedText.toCharArray(), 0, injectedText.length());

如果合适的话。这是因为最终的ContentHandler 实际上ToTextContentHandler 的一个实例,characters( ... ) 方法只是将chars 的序列添加到java.io.Writer 实例(是的,我也从未听说过:非常简单)。

希望这会有所帮助。现在已经将我的这个新班级提交给 Tika 项目,看看他们是否喜欢它的外观。

【讨论】:

  • 您是否有机会在Apache Tika JIRA 中提出错误,并将您的更改上传到ODF 解析器?然后我们可以将这些改进应用到 Tika 中!
  • 哇,很荣幸被邀请……会的。现在它(.odt 脚注/尾注)工作得很好:就像 .docx 处理一样,除了我发现由于某种原因 Tika .docx 解析器将 .docx 中的脚注“1”报告为脚注“2”,脚注“2”为“3”,等等:我的 .odt 解析器得到这些数字是正确的。会引发这两个错误...
猜你喜欢
  • 2015-07-16
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
相关资源
最近更新 更多