Перейти к основному содержимому

Контент-анализ с Apache Tika

· 6 мин. чтения

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. API парсера

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

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

Значения параметров этого метода:

  • stream экземпляр InputStream , созданный из документа для анализа
  • обработчик объект ContentHandler , получающий последовательность событий XHTML SAX, проанализированных из входного документа; этот обработчик затем будет обрабатывать события и экспортировать результат в определенной форме
  • метаданные объект метаданных , передающий свойства метаданных в парсер и из него.
  • context экземпляр ParseContext , несущий контекстно-зависимую информацию, используемую для настройки процесса синтаксического анализа.

Метод parse генерирует исключение IOException , если ему не удается прочитать входной поток, исключение TikaException , если документ, взятый из потока, не может быть проанализирован, и исключение SAXException , если обработчик не может обработать событие.

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

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

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

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

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

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

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

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

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

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

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

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

4.2. Обнаружение языка

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

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

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

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

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

5. Тика в действии

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

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

public class TikaAnalysis {
// illustration methods
}

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

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

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();
}

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

@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 найти правильный тип носителя благодаря магическим байтам %PDF в начале файла.

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

public static String detectDocTypeUsingFacade(InputStream stream) 
throws IOException {

Tika tika = new Tika();
String mediaType = tika.detect(stream);
return mediaType;
}

5.2. Извлечение контента

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

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();
}

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

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

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

@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();
}

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

public static String extractContentUsingFacade(InputStream stream) 
throws IOException, TikaException {

Tika tika = new Tika();
String content = tika.parseToString(stream);
return content;
}

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

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

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;
}

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

@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();
}

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

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

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

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

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

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

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