«1. Обзор

Apache Tika — это набор инструментов для извлечения содержимого и метаданных из различных типов документов, таких как Word, Excel и PDF, или даже мультимедийных файлов, таких как JPEG и MP4.

Все текстовые и мультимедийные файлы можно анализировать с помощью общего интерфейса, что делает Tika мощной и универсальной библиотекой для анализа контента.

В этой статье мы познакомимся с Apache Tika, в том числе с его API синтаксического анализа и с тем, как он автоматически определяет тип содержимого документа. Также будут предоставлены рабочие примеры для иллюстрации работы этой библиотеки.

2. Начало работы

Для анализа документов с помощью Apache Tika нам нужна только одна зависимость Maven:

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

Последнюю версию этого артефакта можно найти здесь.

3. Parser API

Parser API — это сердце Apache Tika, позволяющее абстрагироваться от сложности операций синтаксического анализа. Этот API основан на одном методе:

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

Значения параметров этого метода следующие:

    поток — экземпляр InputStream, созданный из обработчика документа для анализа — объект ContentHandler, получающий последовательность События XHTML SAX, проанализированные из входного документа; затем этот обработчик будет обрабатывать события и экспортировать результат в метаданные определенной формы — объект метаданных, передающий свойства метаданных в контексте синтаксического анализатора и из него — экземпляр ParseContext, несущий контекстно-зависимую информацию, используемую для настройки процесса синтаксического анализа ~ ~~ Метод parse генерирует исключение IOException, если ему не удается прочитать входной поток, исключение TikaException, если документ, взятый из потока, не может быть проанализирован, и исключение SAXException, если обработчик не может обработать событие.

При анализе документа Tika пытается максимально повторно использовать существующие библиотеки анализаторов, такие как Apache POI или PDFBox. В результате большинство классов реализации Parser являются просто адаптерами для таких внешних библиотек.

В разделе 5 мы увидим, как можно использовать параметры обработчика и метаданных для извлечения содержимого и метаданных документа.

Для удобства мы можем использовать фасадный класс Tika для доступа к функциям Parser API.

4. Автоматическое определение

Apache Tika может автоматически определять тип документа и его язык на основе самого документа, а не дополнительной информации.

4.1. Обнаружение типа документа

Обнаружение типов документов может быть выполнено с помощью класса реализации интерфейса Detector, который имеет единственный метод:

Этот метод берет документ и связанные с ним метаданные — затем возвращает объект MediaType, описывающий наилучшее предположение относительно типа документа.

MediaType detect(java.io.InputStream input, Metadata metadata) 
  throws IOException

Метаданные — не единственный источник информации, на который опирается детектор. Детектор также может использовать магические байты, которые представляют собой специальный шаблон в начале файла, или делегировать процесс обнаружения более подходящему детектору.

На самом деле алгоритм, используемый детектором, зависит от реализации.

Например, детектор по умолчанию сначала работает с магическими байтами, а затем со свойствами метаданных. Если тип контента не был найден на этом этапе, он будет использовать загрузчик служб, чтобы обнаружить все доступные детекторы и попробовать их по очереди.

4.2. Определение языка

Помимо типа документа, Tika также может определить его язык даже без помощи метаданных.

В предыдущих выпусках Tika язык документа определялся с помощью экземпляра LanguageIdentifier.

Однако LanguageIdentifier устарел в пользу веб-сервисов, что не указано в документации по началу работы.

Службы определения языка теперь предоставляются через подтипы абстрактного класса LanguageDetector. Используя веб-службы, вы также можете получить доступ к полноценным службам онлайн-перевода, таким как Google Translate или Microsoft Translator.

Для краткости мы не будем подробно останавливаться на этих сервисах.

5. Tika в действии

В этом разделе показаны возможности Apache Tika на рабочих примерах.

«Методы иллюстрации будут заключены в класс:

5.1. Определение типов документов

public class TikaAnalysis {
    // illustration methods
}

Вот код, который мы можем использовать для определения типа документа, прочитанного из InputStream:

Предположим, у нас есть файл PDF с именем tika.txt в пути к классам. Расширение этого файла было изменено, чтобы попытаться обмануть наш инструмент анализа. Реальный тип документа все еще может быть найден и подтвержден тестом:

public static String detectDocTypeUsingDetector(InputStream stream) 
  throws IOException {
    Detector detector = new DefaultDetector();
    Metadata metadata = new Metadata();

    MediaType mediaType = detector.detect(stream, metadata);
    return mediaType.toString();
}

Понятно, что неправильное расширение файла не может помешать Tika найти правильный тип носителя, благодаря магическим байтам %PDF в начало файла.

@Test
public void whenUsingDetector_thenDocumentTypeIsReturned() 
  throws IOException {
    InputStream stream = this.getClass().getClassLoader()
      .getResourceAsStream("tika.txt");
    String mediaType = TikaAnalysis.detectDocTypeUsingDetector(stream);

    assertEquals("application/pdf", mediaType);

    stream.close();
}

Для удобства мы можем переписать код обнаружения, используя класс фасада Tika, с тем же результатом:

5.2. Извлечение содержимого

public static String detectDocTypeUsingFacade(InputStream stream) 
  throws IOException {
 
    Tika tika = new Tika();
    String mediaType = tika.detect(stream);
    return mediaType;
}

Теперь давайте извлечем содержимое файла и вернем результат в виде строки с помощью Parser API:

Учитывая файл Microsoft Word в пути к классам с этим содержимым:

public static String extractContentUsingParser(InputStream stream) 
  throws IOException, TikaException, SAXException {
 
    Parser parser = new AutoDetectParser();
    ContentHandler handler = new BodyContentHandler();
    Metadata metadata = new Metadata();
    ParseContext context = new ParseContext();

    parser.parse(stream, handler, metadata, context);
    return handler.toString();
}

~ ~~ Содержимое можно извлечь и проверить:

Apache Tika - a content analysis toolkit
The Apache Tika™ toolkit detects and extracts metadata and text ...

Опять же, класс Tika можно использовать для более удобного написания кода:

@Test
public void whenUsingParser_thenContentIsReturned() 
  throws IOException, TikaException, SAXException {
    InputStream stream = this.getClass().getClassLoader()
      .getResourceAsStream("tika.docx");
    String content = TikaAnalysis.extractContentUsingParser(stream);

    assertThat(content, 
      containsString("Apache Tika - a content analysis toolkit"));
    assertThat(content, 
      containsString("detects and extracts metadata and text"));

    stream.close();
}

5.3. Извлечение метаданных

public static String extractContentUsingFacade(InputStream stream) 
  throws IOException, TikaException {
 
    Tika tika = new Tika();
    String content = tika.parseToString(stream);
    return content;
}

В дополнение к содержимому документа Parser API также может извлекать метаданные:

Если в пути к классам существует файл Microsoft Excel, этот тест подтверждает правильность извлеченных метаданных: ~ ~~

public static Metadata extractMetadatatUsingParser(InputStream stream) 
  throws IOException, SAXException, TikaException {
 
    Parser parser = new AutoDetectParser();
    ContentHandler handler = new BodyContentHandler();
    Metadata metadata = new Metadata();
    ParseContext context = new ParseContext();

    parser.parse(stream, handler, metadata, context);
    return metadata;
}

Наконец, вот еще одна версия метода извлечения с использованием класса фасада Tika:

@Test
public void whenUsingParser_thenMetadataIsReturned() 
  throws IOException, TikaException, SAXException {
    InputStream stream = this.getClass().getClassLoader()
      .getResourceAsStream("tika.xlsx");
    Metadata metadata = TikaAnalysis.extractMetadatatUsingParser(stream);

    assertEquals("org.apache.tika.parser.DefaultParser", 
      metadata.get("X-Parsed-By"));
    assertEquals("Microsoft Office User", metadata.get("Author"));

    stream.close();
}

6. Заключение

public static Metadata extractMetadatatUsingFacade(InputStream stream) 
  throws IOException, TikaException {
    Tika tika = new Tika();
    Metadata metadata = new Metadata();

    tika.parse(stream, metadata);
    return metadata;
}

Это руководство посвящено анализу контента с помощью Apache Tika. Используя API-интерфейсы Parser и Detector, мы можем автоматически определять тип документа, а также извлекать его содержимое и метаданные.

Для расширенных вариантов использования мы можем создать собственные классы Parser и Detector, чтобы иметь больший контроль над процессом синтаксического анализа.

Полный исходный код этого руководства можно найти на GitHub.

«