2012-08-22 26 views
1

我试图解析mbox格式的电子邮件。然而,提卡不停地尝试使用TNEFParser这些消息导致错误:防止使用TNEFParser的Tika

2012-08-21 17:44:42,139 FATAL org.apache.hadoop.mapred.Child: Error running child : java.lang.OutOfMemoryError: Java heap space 
    at org.apache.poi.hmef.attribute.TNEFAttribute.<init>(TNEFAttribute.java:50) 
    at org.apache.poi.hmef.attribute.TNEFAttribute.create(TNEFAttribute.java:76) 
    at org.apache.poi.hmef.HMEFMessage.process(HMEFMessage.java:74) 
    at org.apache.poi.hmef.HMEFMessage.process(HMEFMessage.java:98) 
    at org.apache.poi.hmef.HMEFMessage.process(HMEFMessage.java:98) 
    at org.apache.poi.hmef.HMEFMessage.<init>(HMEFMessage.java:63) 
    at org.apache.tika.parser.microsoft.TNEFParser.parse(TNEFParser.java:80) 
    at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242) 
    at org.apache.tika.parser.mail.MailContentHandler.body(MailContentHandler.java:102) 
    at org.apache.james.mime4j.parser.MimeStreamParser.parse(MimeStreamParser.java:133) 
    at org.apache.tika.parser.mail.RFC822Parser.parse(RFC822Parser.java:76) 
    at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242) 
    at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242) 
    at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:120) 
    at org.lab41.asf.etl.mapred.MailboxToTextMapper.parse(MailboxToTextMapper.java:124) 
    at org.lab41.asf.etl.mapred.MailboxToTextMapper.map(MailboxToTextMapper.java:88) 
    at org.lab41.asf.etl.mapred.MailboxToTextMapper.map(MailboxToTextMapper.java:45) 
    at org.apache.avro.mapred.HadoopMapper.map(HadoopMapper.java:81) 
    at org.apache.avro.mapred.HadoopMapper.map(HadoopMapper.java:34) 
    at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50) 
    at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:391) 
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:325) 
    at org.apache.hadoop.mapred.Child$4.run(Child.java:266) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:396) 
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1278) 
    at org.apache.hadoop.mapred.Child.main(Child.java:260) 

是否有可能阻止从蒂卡使用TNEFParser?任何的意见都将会有帮助。

回答

2

为了长期解决,您应该将此报告为Apache Tika中的错误,将有问题的文件附加到错误报告中,并使用该项目修复错误。

短期内,解压缩Tika-Parsers jar文件,编辑META-INF/services/org.apache.tika.parser.Parser文件并从列表中删除TNEF解析器。这将停止它自动加载和使用AutoDetectParser

没有更改Tika解析器jar文件,这有点棘手。有两个选项可用。一个是自己创建一个TikaConfig实例,而不是依靠默认的实例,只提供一个有限的解析器列表。根据您是否想要白名单或黑名单,这可能很容易或更难。或者,您可以使用mimetype的最后注册解析器获胜。所以,用服务文件和你自己的虚拟解析器创建你自己的jar。让解析器声明它处理TNEF mimetype,但它没有做任何事情。将jar添加到您的类路径中,然后使用您的虚拟解析器代替

+0

我结束了解压罐。 –

2

以下是@Gagravarr建议的编程版本。它用EmptyParser替换已注册的不必要的解析器。

private Tika createTika(final Parser... unnecessaryParsers) 
     throws TikaException, IOException { 
    final TikaConfig config = new TikaConfig(); 
    final AutoDetectParser autoDetectParser = new AutoDetectParser(config); 

    final Set<MediaType> unnecessaryMimeTypes = 
     getUnnecessaryMediaTypes(unnecessaryParsers); 
    disableParsing(autoDetectParser, unnecessaryMimeTypes); 

    final Detector detector = config.getDetector(); 
    final Tika tika = new Tika(detector, autoDetectParser); 
    return tika; 
} 

private Set<MediaType> getUnnecessaryMediaTypes(
     final Parser... unnecessaryParsers) { 
    final Set<MediaType> unnecessaryTypes = new HashSet<MediaType>(); 
    for (final Parser unnecessaryParser: unnecessaryParsers) { 
     final Set<MediaType> supportedTypes = 
      unnecessaryParser.getSupportedTypes(null); 
     unnecessaryTypes.addAll(supportedTypes); 
    } 
    return unnecessaryTypes; 
} 

private void disableParsing(final CompositeParser mainParser, 
     final Set<MediaType> unnecessaryMediaTypes) { 
    final EmptyParser emptyParser = new EmptyParser(); 

    final Map<MediaType, Parser> parsers = mainParser.getParsers(); 
    for (final MediaType unnecessaryType: unnecessaryMediaTypes) { 
     parsers.put(unnecessaryType, emptyParser); 
    } 

    mainParser.setParsers(parsers); 
} 

用法:

final Parser unnecessaryParser = new MP4Parser(); 
final Tika tika = createTika(unnecessaryParser); 

你也可以用它来避免TIKA-1040: Could not delete temporary file

3

这是@Gagravarr建议的配置版本。

Firsly,创建蒂卡-config.xml文件:

<properties> 
    <parsers> 

    <!-- use the default parser in most cases, it is a composite of all 
     the parsers listed in META-INF/services/org.apache.tika.parser.Parser --> 
    <parser class="org.apache.tika.parser.DefaultParser"/> 

    <!-- Disable tnef extraction-->  
    <parser class="org.apache.tika.parser.EmptyParser"> 
     <mime>application/vnd.ms-tnef</mime> 
     <mime>application/x-tnef</mime> 
    </parser> 

    </parsers> 
</properties> 

现在,从这个配置创建一个TikaConfig(假设它是在classpath中某处):

ClassLoader loader = Thread.currentThread().getContextClassLoader(); 
TikaConfig config = new TikaConfig(loader.getResource("tika-config.xml"), loader); 

当你克雷娅察一个新的解析器,或使用蒂卡立面,通过您的配置:

AutoDetectParser parser = new AutoDetectParser(config); 
ParseContext context = new ParseContext(); 
context.set(Parser.class, parser); 
parser.parse(input, handler, metadata, context); 

任何文件标识为TNEF将使用EmptyParser,它不返回任何内容,也不实际解析任何内容。

这实际上是一个黑名单,如果您想要白名单,您需要从XML中删除DefaultParser并手动配置每个解析器及其元数据。