0
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

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

Deprecated:

この記事は非推奨です。

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

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


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

PDFMiner とかはちょっと構造が複雑になると全然駄目なので、ここはやはりApacheか…みたいな。

サンプルは 平成29年版 厚生労働白書 で試してみる。

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 プラグインを使うといいらしい。
細かいところはよくわかってないけど、だいたい usage の通りでいけるはず。

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

dockerでやる

名前は適当に。

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

ビルドして、

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

起動。

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

実行

下準備

HOST='localhost:9200'

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

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

pipeline を設定

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

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

pdfをbase64化して投入

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

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

結果を取り出す

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

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

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

で、

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

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

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

っていう話。

余談

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

にたどり着いたので、

とりあえず手元の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にお願いしたので

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
0
Help us understand the problem. What are the problem?