elasticsearch経由でPDFの中身のテキストを抜き出す話

# Deprecated:

**この記事は非推奨です。**

掲題の目的ならもっとカンタンな以下の方法で大丈夫。
https://qiita.com/arc279/items/5b6cf2d0b24ce5a50cae

試行錯誤の過程を残しておく目的で消さないけど、
以下はほとんどelasticsearchのingest-attachmentプラグインの紹介みたいな感じになってます。

---

なんか全文検索な本来の目的とは違うような気がするけど、副産物利用。

[PDFMiner](https://github.com/euske/pdfminer) とかはちょっと構造が複雑になると全然駄目なので、ここはやはりApacheか…みたいな。

サンプルは [平成29年版 厚生労働白書](http://www.mhlw.go.jp/wp/hakusyo/kousei/17/dl/all.pdf) で試してみる。

```sh
wget http://www.mhlw.go.jp/wp/hakusyo/kousei/17/dl/all.pdf
```

結果をgistに置いときます。（1.6Mのテキストなのでけっこうでかい）
https://gist.github.com/arc279/21e5257b24cda1a652ff48601fc29366

考察とかは後述。

ぶっちゃけ「おぉっ！」ってなるほど精度は高くないけど、pdfのまま扱うよりテキストとして扱うほうが圧倒的に楽なので、
元のpdfと付き合わせながらテキストからコーパスを整えたりしていくといいんじゃないかと。


# elasticsearch

[ingest-attachment](https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest-attachment.html) プラグインを使うといいらしい。
細かいところはよくわかってないけど、だいたい [usage](https://www.elastic.co/guide/en/elasticsearch/plugins/master/using-ingest-attachment.html) の通りでいけるはず。

ちなみに `doc` とか `xls` とか `ppt` とかのOfficeファイルもいけるらしい。
本来の全文検索用途でも使える。

## dockerでやる

名前は適当に。

```text:kuryu-es-sample/Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:6.0.1
LABEL maintainer "kuryu <revision279@gmail.com>"

RUN elasticsearch-plugin install analysis-icu
RUN elasticsearch-plugin install analysis-kuromoji
RUN elasticsearch-plugin install ingest-attachment
```

ビルドして、

```sh
docker build --no-cache -t kuryu/es kuryu-es-sample
```

起動。

```yaml:docker-compose.yml
version: '2.2'
services:
  elasticsearch:
    image: kuryu/es
    container_name: elasticsearch
    environment:
      - cluster.name=dev-kuryu-cluster
      - node.name=dev-kuryu-01
      - log4j2.disable.jmx=true
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms1024m -Xmx1024m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - ./volumes/esdata1:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
```

```
docker-compose up
```

## 実行

### 下準備

```sh
HOST='localhost:9200'
```

あと、毎回ヘッダ書くのがめんどくさいのでcurlの設定ファイル書いておく。

```text:.curlrc
-s
-H "Content-Type: application/json"
-H "X-Config-File: .curlrc"
```

### pipeline を設定

`data`フィールドに生データを `base64` して放り込めば `my-attachment` パイプラインに流れるようにする。

```sh
curl -K .curlrc -XPUT "${HOST}/_ingest/pipeline/my-attachment?pretty" -d '
{
  "description" : "Extract attachment information",
  "processors" : [
    {
      "attachment" : {
        "field" : "data",
        "indexed_chars" : -1
      }
    }
  ]
}
'
```

```text:result
{
  "acknowledged" : true
}
```

### pdfをbase64化して投入

`data`フィールドに生データを `base64` して放り込む。

```sh
cat <<-EOD | curl -K .curlrc -X POST "${HOST}/test-ingest/pdf/1?pipeline=my-attachment&pretty" -d @-
{
  "data": "$(base64 -w 0 'all.pdf')"
}
EOD
```

```text:result
{
  "_index" : "test-ingest",
  "_type" : "pdf",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
```

### 結果を取り出す

```sh
curl -K .curlrc -XGET "${HOST}/test-ingest/pdf/1" > 1.json
```

でjsonで結果が返ってきて、 `_source` の下に抽出された文章が入っているので、そこから `jq` で抜き出す。

```sh
cat 1.json | jq -r ._source.attachment.content
```

# で、

* 見出しとかキャプションとかは変なところで切れてしまったり、
* 図とか段組みは縦書きに認識されてしまったり、
* 全体的に図というか絵みたいになってるページはまるごとスルーされたり、

するけど、文章の塊はわりとしっかり抜けてる感じ。

pdfの中身は文書ではなくグラフみたいなもので、全く構造化されてないから最悪や、的なDISを見たことがあるけど、
ほんとその通りで真面目にやろうとすると大変つらい。

っていう話。


# 余談

どうやってpdfの中身抽出してるのか中身を追ってみたら

* elasticsearch
    * [Apache Tika](https://tika.apache.org/)
        * [Apache PDFBox](https://pdfbox.apache.org/)

にたどり着いたので、

とりあえず手元のmacで

```
java -jar pdfbox-app-2.0.8.jar  ExtractText a.pdf
```

とかやろうとしたら

```
Exception in thread "main" java.lang.UnsupportedOperationException: TTF fonts do not have a CFF table
```

とか出てこけた。

で、原因と思しきフォント周り調べてて危うく死にかけた。
TTFがOTFの流れを汲むCFFをType42がCIDFontType2だかなんだかで何言ってんのかさっぱりわからん。

https://fontforge.github.io/ja/cidmenu.html
http://blog.antenna.co.jp/PDFTool/archives/2006/05/pdf_24_cidkeyed.html

詳しくはこのあたりを見て、ぜひ「なにいってだこいつ」感を味わって頂きたい。

おわり。

## 余談の余談

というか、これ

```
Exception in thread "main" java.lang.UnsupportedOperationException: TTF fonts do not have a CFF table
```

が手元で解決できればわざわざelasticsearch経由しなくてもpdfbox単体でいけると思う。
＃解決の目処が立ちそうになかったからelasticsearchにお願いしたので