LoginSignup
2
2

More than 5 years have passed since last update.

ApacheTikaを使ってRubyからPDFの本文抽出

Posted at

やりたいこと

PDFの本文をページごとに抽出したい。
(将来的に、指定したキーワードにヒットするのは何ページか?といった使い方をする)

コードなど

RubyGemsを調べてみると、既にTika-ClientというGemが存在していたのだけど、
やりたいことは決まってるしそこまで汎用的に作る必要も無いのでイチからサクッと書いてみた。
外部コマンドを実行してその結果をパースするだけ。

require "nokogiri"

module Rtika
  class Core
    attr_reader :tika_path

    def initialize tika_path: ""
        @tika_path = tika_path
        raise "java was not installed!" unless system("java -version")
        raise "tika was not found!" unless File.exists? tika_path
    end

    def exec document_path: ""
        raise "document was not found!" if document_path == ""

        command = "java -jar #{tika_path}"
        type = "x"
        encoding = "UTF-8"
        ret = `#{command} -#{type} --encoding=#{encoding} #{document_path}`
        html = Nokogiri::HTML.parse(ret)
        body = html.css("body > div.page").map{|page| page.css("p").text  }
        body.map.with_index{|r, i| {page: i+1, content: r} }
    end
  end
end

tikaはJSONフォーマットで抽出することもできるのだけど、抽出したJSONをRubyでJSON.parseするとパースエラーを起こしてしまう。
原因が掴めなかったので、xml形式で抽出し、Nokogiriで各ページの内容を削り取ることにした。

Enumerator#with_indexを知ったのが今回の収穫。

Rtika::Core.new(tika_path: "./jar/tika-app-1.14.jar").exec(document_path: "sample_document.pdf")

実行結果

[
    [ 0] {
           :page => 1,
        :content => "1ページ目のページ内容"
    },
    [ 1] {
           :page => 2,
        :content => "2ページ目のページ内容"
    },
    [ 2] {
           :page => 3,
        :content => "3ページ目のページ内容"
    },
    [ 3] {
           :page => 4,
        :content => "4ページ目のページ内容"
    },
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2