やりたいこと
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ページ目のページ内容"
},