Press "Enter" to skip to content

Apache Tika实战

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

Apache Tika实战

 

Tika 简介

 

Apache Tika 是一个内容分析工具包,可以检测 上千种文件类型 ,并提取它们的 元数据和文本 。tika在设计上十分精巧,单一的接口使它易于使用,在 搜索引擎索引,内容分析,翻译 等诸多方面得到了广泛使用。

 

Apache Tika曾经是 Apache Lucene 的一个子项目,现已成为Apache顶级项目。

 

Tika的特点

 

 

    1. 支持上千种不同的文件类型

 

    1. 提供了多种实用工具,如tika-app, tika-server等

 

    1. 除了Java,还提供了其他编程语言的调用,如Julia,Python

 

    1. 扩展性很好,支持自定义文件类型和解析器

 

 

Tika的组成

 

tika的核心是一个类库,提供了文件类型检测,内容语言检测等功能,并有一个完整的解析器框架,通过这个框架集成了许多Java平台上流行的文件分析工具,如针对压缩格式,使用了commons-compress,针对微软Office文档,使用了Apache POI,针对Adobe PDF格式,采用了Apache PDFbox

 

tika-core && tika-parsers

 

tika-core是tika的核心,提供了文件类型检测,语言检测,以及解析器框架。

 

tika-core并不包含具体的解析器,而是提供了一个api,实际的解析器实现放在tika-parsers中。

 

tika-parsers具有非常的传递依赖,使用时应该注意和项目已有依赖的冲突问题

 

tika-app

 

tika-app包含了tika核心类库和它的相关依赖,提供了命令行工具和图形用户界面,可以在脚本中使用,并支持管道。

 

 

 

tika-server

 

一个restful服务,方便和现有应用系统集成

 

$ curl -X PUT --data-binary @GeoSPARQL.pdf http://localhost:9998/tika --header "Content-type: application/pdf"
$ curl -T price.xls http://localhost:9998/tika --header "Accept: text/html"

 

tika-bundle

 

一个OSGi bundle,方便和基于OSGi的应用系统集成

 

OSGi: 开放服务网关协议,支持模块的动态加载,热拔插,可以在不停机的情况下,让应用程序加载新的模块,并提供新的服务

 

tika-eval

 

一个命令行工具,可以批量解析文件,然后把结果保存到数据库,支持多种类型的数据库,如h2,mysql……

 

默认数据库为h2,使用其他类型的数据库需要在启动时将相关的依赖放到classpath下

 

感觉是为Lucene准备的,提取文件内容后,保存到数据库,然后再由索引器进行索引,最后对外提供搜索服务

 

tika设计&实现

 

tika的核心功能是文件内容分析,这里分析主要有两个含义,一是提取文件的元数据(Metadata),包括文件类型,版本,作者,编辑工具,压缩算法等;二是解析文件得到文本内容(Text),这里的文本是指在相应的阅览软件中打开文件时看到的内容。

 

为了实现上述目标,tika设计了一个扩展性极强的框架,主要包括文件类型检测和内容解析两个部分。首先判断文件类型(Detector),再根据文件类型选用适当的解析器(Parser),解析结果保存在Metadata和ContentHandler中,我们可以通过自定义ContentHandler来得到想要的信息。

 

 

文件类型检测

 

文件类型检测是处理文件的第一个步骤,在大部分情况下,我们可以根据文件名简单判断出文件的类型,这样处理的效率很高,但是结果并不精准(因为文件名可以轻松伪造),因此Tika设计了一个检测器接口,并采用了几种更加完备的策略来检测文件类型。

 

//org.apache.tika.detect.Detector
MediaType detect(InputStream stream, Metadata metadata) throws IOException;

 

文件类型检测机制

 

 

    1. 文件名检测 – 简单地根据文件后缀名判断文件类型。

 

    1. 魔术字检测 – 有些文件格式会将文件最开始的几个字节设置会特定的模式,通过这些特殊的字节模式,可以判断文件类型。

 

    1. 容器格式检测 – 有些文件格式是一种容器格式,这一类文件无法通过魔术字判断出文件类型,需要对容器内的数据做更多的分析,如微软Office文档(.docx, .xlsx, .pptx)这些文档实际上都是zip压缩文件,魔术字是一样的。

 

 

容器格式检测耗时比较长,最坏的情况下需要读取整个文件

 

文件类型的检测顺序

 

容器格式检测(OLE2ContainerDetector, ZipContainerDetector……)=>

 

魔术字检测(MimeTypes)=>

 

文件名检测(MimeTypes)

 

MimeTypes底层实际使用了NameDetector和MagicDetector

 

解析器

 

Parser是tika的核心概念,它隐藏了不同文件格式和解析库的复杂性,为客户端程序提供了一个简单而强大的机制,用来从各种各样的文档中提取元数据和结构化文本内容。tika提供了很多解析器,用来对各种各种的文件类型进行处理,如针对微软Office文档的OfficeParser,针对Adobe PDF文档的PDFParser,针对压缩文件的CompressorParser,针对归档文件的PackageParser,还有一些特殊的Parser,如TesseractOCRParser,用来对图片进行OCR内容提取

 

如果服务器安装了tesseract,那幺TesseractOCRParser就会被启用,在实时分析系统中,TesseractOCRParser的性能是不可接受的,建议手动禁用掉

 

void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException;

 

接口说明

 

参数 说明
InputStream 待解析的文档,以字节流形式传入,可以避免tika占用太多内存
ContentHandler 内容处理器,用来收集结果,Tika会将解析结果包装成XHTML SAX event进行分发,通过ContentHandler处理这些event就可以得到文本内容和其他有用的信息
Metadata 元数据,既是输入也是输出,可以将文件名或者可能的文件类型传入,tika解析时可以根据这些信息判断文件类型,再调用相应的解析器进行处理;另外,tika也会将一些额外的信息保存到Metadata中,如文件修改日期,作者,编辑工具等
ParseContext 解析上下文,用来控制解析过程,比如是否提取Office文档里面的宏等

 

扩展机制

 

 

    1. 定义Mimetype(可选,如果需要处理一些特殊文件,它们的文件类型tika目前并不支持,就需要自定义Mimetype)

 

    1. 实现Parser,可以针对tika已有的文件类型编写自己的解析器,也可以创建支持新的文件类型的解析器

 

    1. 注册Parser,通过SPI机制可以轻松地将自己的解析器放进tika的解析器库里(CompositeParser)

 

      1. 在类路径下创建文件 – META-INF/services/org.apache.tika.parser.Parser

 

      1. 文件内容就是自定义的Parser的全路径类名

 

 

 

其他tika组件(如类型检测器,翻译器,语言检测器等)也使用该机制进行扩展

 

注意事项

 

配置

 

tika在启动时可以加载一个配置文件,通过这个文件可以对tika-core的各个组件进行配置,可以配置Parser,Detector,Mimetype, ServiceLoader……

 

<?xml version="1.0" encoding="UTF-8"?>
<properties>
    <detector>
        <detector-exclude/>
        <detector-exclude/>
    </detector>
  <parsers>
    <!-- Default Parser for most things, except for 2 mime types, and never use the Executable Parser -->
    <parser>
      <mime-exclude>image/jpeg</mime-exclude>
      <mime-exclude>application/pdf</mime-exclude>
      <parser-exclude/>
    </parser>
    <!-- Use a different parser for PDF -->
    <parser>
      <mime>application/pdf</mime>
    </parser>
  </parsers>
</properties>

 

安全问题

 

tika设计了一个扩展性很好的解析器框架,但是具体的解析任务交给了外部的各种开源工具,因此也带来了很多安全问题,在实际使用中推荐使用最新版本的类库。

 

!!! 另外,tika有线程死锁的问题,可能导致服务器CPU资源耗尽,建议在容器(如docker)里运行,或者使用tika-server

 

图像,音频,视频

 

tika可以从图像,音频,视频文件中提取元数据,但是几乎无法提取出任何有价值的文本内容,在大多数场景下建议禁用这些类型的Parser

 

针对图像,可以使用TesseractOCRParser进行OCR操作,这需要服务器安装了tesseract,OCR的效率很低,普通文件的解析一般在几十毫秒左右,OCR的耗时约为几秒钟;而且OCR的结果依赖于算法模型的训练,需要整理出合适,足够的样本,工作量比较多。

 

解析时间跟文件大小和服务器性能有关系,数据来自对8M以下互联网文件的解析

 

文件修复

 

tika可以在解析时对文件进行一定程度的修复

 

比如,ZipSalvager可以对基于ZipContainer格式的文件进行修复

 

为了将解析耗时控制在一定范围内,不得不对大文件进行截断

 

提取其他信息

 

tika的解析逻辑默认只会保留元数据(Metadata)和文本(Text),如果对其他信息感兴趣,就需要对ContentHandler进行定制

 

tika提供了很多有用的ContentHandler,

 

比如ToXMLContentHandler将以XML形式输出文件的文本内容,

 

WriteLimitContentHandler可以在解析得到一定字符数的结果后,中断解析过程(抛出异常),

 

LinkContentHandler可以收集文件内容中的超链接,

 

PhoneContentHandler可以收集文件内容中的电话号码。

 

提取压缩文件里的文件名

 

默认配置下,tika解析压缩文件(.gz, .bzip2等)和归档文件(.zip, .tar, .7z等)时,文件名会和文件内容杂糅在一起,如果需要区分开,可以自定义一个ContentHandler对 class="embedded" 的XHTML SAX event进行处理

 

Tika对压缩文件内文件名的提取实现不完整,遇到特殊情况建议手动处理,重写Parser

 

提取图片

 

某些文件(主要是容器文件格式)内部可能含有其他内嵌文件,如压缩文件,Word文档,PDF文档等,tika可以递归处理压缩文件内部的子文件,但是除此之外没有提供别的处理方法。

 

如果想要提取微软Office文档或者PDF文档内的图片,建议在tika的解析器框架下自己实现Parser,将图片写入的逻辑加上;或者直接使用具体的解析库额外处理(比如使用Apache POI可以很方便的提取微软Office文档里的图片)

 

tika的局限性

 

tika支持上千种文件类型,并且提供了统一的接口,非常容易上手;但是有些文件格式非常复杂,可能会出现支持不完善的情况,如对压缩文件的解析依赖commons-compress,但是commons-compress对压缩文件的支持就不完整,所以tika在处理某些文件时无法得到有用信息

 

tika的性能

 

tika的解析器本质上是一个适配器,底层使用了很多第三方开源工具来实现具体的内容解析,因此tika的解析效率也跟这些工具有关

 

对某个具体文件来说,解析耗时主要跟文件大小,文件格式的复杂程度,压缩算法,服务器性能等关系较大

 

实时系统中最好限制一下文件大小,推荐在离线环境中使用

 

简单使用

 

tika是一个工具集,包括类库,cli,gui,rest服务等,如何使用需要根据具体场景进行选择。以下给出了tika作为类库使用时的一些demo,更多的例子可以参考 http://tika.apache.org/1.24.1/examples.html

 

 

    1. 引入依赖

 

 

pom.xml

 

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.24.1</version>
  </dependency>

 

示例

 

//Parsing using the Tika Facade
public String parseToStringExample() throws IOException, SAXException, TikaException {
    Tika tika = new Tika();
    try (InputStream stream = ParsingExample.class.getResourceAsStream("test.doc")) {
        return tika.parseToString(stream);
    }
}
//Parsing using the Auto-Detect Parser
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();
    }
}
//Picking different output formats
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();
    }
}

 

参考

 

 

    1. 白宁超 –

Tika常见格式文件抽取内容并做预处理
Tika官方文档

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注