1.介紹
Tika 是一個內容抽取的工具集合 (a toolkit for text extracting) 。它集成了 POI 和 Pdfbox,並且爲文本抽取工作提供了一個統一的界面。其次,Tika 也提供了便利的擴展 API,用來豐富其對第三方文件格式的支持。
2.依賴
tika-core包含Tika的核心接口和類,用於在不需要完整的parser工具集的情況下,通過下面配置添加maven依賴:
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.24</version>
</dependency>
如果你希望使用tika解析文檔(不僅僅是識別文檔類型),可以通過下面配置添加依賴:
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.24</version>
</dependency>
請注意,添加此依賴項將向項目引入許多可傳遞的依賴項,包括tika core上的依賴項。您需要確保這些依賴項不會與現有項目依賴項衝突。可以在tika parsers目錄中使用以下命令來獲得所有依賴項的完整列表。
mvn dependency:tree | grep :compile
更多上下游工具:
- tike-app
Tika應用程序。將上述組件和所有外部解析器庫組合成一個帶有GUI和命令行界面的可運行jar。 - tika-server
Tika的JAX-RS REST服務應用,基於Jetty服務器運行Tika Rest服務。 - tika-bundle
Tika的一個OSGi包,它將tika解析器與非OSGified解析器庫結合起來,使它們易於在OSGi環境中部署。 - tika-eval
Tika評估模塊。命令行工具,用於評估Tika的輸出或比較Tika或其他文本提取包的兩個不同版本的輸出。 - 其他語言包裝
在另一種編程語言(如Julia或Python)中,有幾個包裝器可以使用Tika。
3.支持的文檔格式
- HTML
- XML
- MS-office
- ODF(OpenDocumentFormat)
- iWorks(Numbers,Pages,Keynote)
- WordPerfect
- ePub
- RTF(RichTextFormat)
- 壓縮文件(tar,ar,arj,cpio,dump,zip,7zip,gzip,bzip2,xz,lzma,z,pac200)
- text
- rss
- audio
- image
- video
- Java class
- 源代碼
- cad
- font
- …
完整列表
4.處理流程
Tika對文檔內容信息的解析處理的流程如下:Tika通過MimeType(MIME是MIME(Multipurpose Internet Mail Extensions)多用途互聯網郵件擴展類型。是設定某種擴展名的文件用一種應用程序來打開的方式類型)來實現對一個文檔的具體識別工作,通過Language identifier來識別語言。根據MimeType和Language identifier的識別結果,選擇調用具體的Parser來解析文檔。而處理則由ContentHandler接口來完成。其中parser負責解析具體的文檔,當解析到需要進行處理的時候,調用具體的信息處理類中的contentHandler進行解析內容的處理。解析、處理後得到的結果作爲返回的值。
另外,關於文檔的元信息會在處理的過程中被解析,並保存在Metadata對象中。比如一個文檔的最後編輯時間,最後的保存時間,標題,作者以及contentType等。這些信息對於用一些關鍵信息進行文檔檢索非常有用。
5.Parser API
org.apache.tika.parser.Parser接口是Tika的核心接口。它隱藏了不同文件格式和解析庫的複雜性,同時爲客戶端應用程序從各種文檔中提取結構化文本內容和元數據提供了簡單而強大的機制。所有這些都是通過一種方法實現的:
void parse(InputStream stream, ContentHandler handler, Metadata metadata,ParseContext context) throws IOException, SAXException, TikaException;
parse方法將要解析的文檔和相關的元數據作爲輸入,並將結果輸出爲XHTML SAX事件和額外的元數據。parse context參數用於指定與任何單個文檔無關的上下文信息(如當前本地)。導致這種設計的主要標準是:
-
Streamed parsing
接口不需要客戶端應用程序或解析器實現來將完整的文檔內容保存在內存中或假脫機到磁盤。這使得即使是巨大的文檔也可以在不需要過多資源的情況下被解析。 -
Structured content
解析器實現應該能夠在提取的內容中包含結構信息(標題、鏈接等)。例如,客戶機應用程序可以使用這些信息來更好地判斷解析文檔的不同部分的相關性。 -
Input metadata
客戶端應用程序應該能夠在要分析的文檔中包含元數據,如文件名或聲明的內容類型。解析器實現可以使用這些信息來更好地指導解析過程。 -
Output metadata
除了文檔內容之外,解析器實現還應該能夠返回文檔元數據。許多文檔格式包含元數據,如作者的姓名,這些元數據可能對客戶端應用程序有用。 -
Context sensitivity
雖然Tika解析器的默認設置和行爲在大多數用例中都應該很好地工作,但是仍然有一些情況需要對解析過程進行更細粒度的控制。在不破壞抽象層的情況下,將這種特定於上下文的信息注入解析過程應該很容易。
6.實例
6.1.使用Tika面板工具解析文檔
Tika facade提供了許多非常快速和簡單的方法來讓Tika解析內容,並返回生成的純文本.
public String parseToStringExample() throws IOException, SAXException,TikaException {
Tika tika = new Tika();
try (InputStream stream = ParsingExample.class.getResourceAsStream("test.doc")) {
return tika.parseToString(stream);
}
}
6.2.使用自動識別解析器
爲了獲得更多的控制,可以直接調用Tika解析器。最有可能的情況是,首先需要使用自動檢測解析器,它會自動找出內容類型,然後調用適當的解析器。
public String parseExample() throws IOException, SAXException, TikaException {
AutoDetectParser parser = new AutoDetectParser();
BodyContentHandler handler = new BodyContentHandler();
Metadata metadata = new Metadata();
try (InputStream stream = ParsingExample.class.getResourceAsStream("test.doc")) {
parser.parse(stream, handler, metadata);
return handler.toString();
}
}
6.3.選擇不同的輸出格式
使用Tika,您可以獲得以多種不同格式返回的文件文本內容。它們可以是純文本、html、xhtml、文件某一部分的xhtml等等,這是根據您提供給解析器的ContentHandler來控制的。
解析爲純文本
使用BodyContentHandler將文檔內容轉化爲純文本。
public String parseToPlainText() throws IOException, SAXException, TikaException {
BodyContentHandler handler = new BodyContentHandler();
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test.doc")) {
parser.parse(stream, handler, metadata);
return handler.toString();
}
}
解析爲XHTML
使用ToXMLContentHandler將文檔內容轉化爲XHTML。
public String parseToHTML() throws IOException, SAXException, TikaException {
ContentHandler handler = new ToXMLContentHandler();
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test.doc")) {
parser.parse(stream, handler, metadata);
return handler.toString();
}
}
如果只需要xhtml文檔的body,而不需要header,可以將BodyContentHandler和ToXMLContentHandler鏈接在一起,如圖所示:
public String parseBodyToHTML() throws IOException, SAXException, TikaException {
ContentHandler handler = new BodyContentHandler(
new ToXMLContentHandler());
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test.doc")) {
parser.parse(stream, handler, metadata);
return handler.toString();
}
}
只獲取XHTML的某些內容
可以對解析結果執行XPath查詢,只獲取XHTML的某些位置。
public String parseOnePartToHTML() throws IOException, SAXException, TikaException {
// Only get things under html -> body -> div (class=header)
XPathParser xhtmlParser = new XPathParser("xhtml", XHTMLContentHandler.XHTML);
Matcher divContentMatcher = xhtmlParser.parse("/xhtml:html/xhtml:body/xhtml:div/descendant::node()");
ContentHandler handler = new MatchingContentHandler(
new ToXMLContentHandler(), divContentMatcher);
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test2.doc")) {
parser.parse(stream, handler, metadata);
return handler.toString();
}
}
6.4.自定義Handler
使用Tika解析文件的文本輸出通過傳遞給parse方法的SAX ContentHandler返回。可以通過提供自己的ContentHandler來定製解析,ContentHandler可以做一些特殊的事情。
將內容中的電話號碼提取到元數據中
通過使用PhoneExtractingContentHandler,您可以在提取的文檔文本內容中找到任何電話號碼,並將其放入元數據對象中。
將純文本分塊流式處理
有時候,你想把得到的文本分塊,也許是爲了儘量減少內存使用,也許是爲了輸出到HDFS文件,或者是其他原因!通過一個小的自定義內容處理程序,您可以做到這一點。
public List<String> parseToPlainTextChunks() throws IOException, SAXException, TikaException {
final List<String> chunks = new ArrayList<>();
chunks.add("");
ContentHandlerDecorator handler = new ContentHandlerDecorator() {
@Override
public void characters(char[] ch, int start, int length) {
String lastChunk = chunks.get(chunks.size() - 1);
String thisStr = new String(ch, start, length);
if (lastChunk.length() + length > MAXIMUM_TEXT_CHUNK_SIZE) {
chunks.add(thisStr);
} else {
chunks.set(chunks.size() - 1, lastChunk + thisStr);
}
}
};
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test2.doc")) {
parser.parse(stream, handler, metadata);
return chunks;
}
}
6.5.翻譯
Tika提供了一個可插入的翻譯系統,允許您將解析結果發送到外部系統或程序,以便將文本翻譯成另一種語言。
使用微軟翻譯api
爲了使用Microsoft翻譯API,您需要註冊一個Microsoft帳戶,獲取一個API密鑰,然後在翻譯之前將密鑰傳遞給Tika。
public String microsoftTranslateToFrench(String text) {
MicrosoftTranslator translator = new MicrosoftTranslator();
// Change the id and secret! See http://msdn.microsoft.com/en-us/library/hh454950.aspx.
translator.setId("dummy-id");
translator.setSecret("dummy-secret");
try {
return translator.translate(text, "fr");
} catch (Exception e) {
return "Error while translating.";
}
}
語種識別
Tika通過LanguageIdentifier類提供了識別文本語種的支持。
public String identifyLanguage(String text) {
LanguageIdentifier identifier = new LanguageIdentifier(text);
return identifier.getLanguage();
}
6.6.更多例子
請閱讀《實戰Tika》,所有的例子都在SVN上的TikaExample模塊。