iTextpdfを使ってPDFデータからテキストデータを抽出する
JavaからPDFを扱うためのライブラリとして、iTextpdfというものがあります。
iText, Programmable PDF software | iText Software
これを利用して、テキストデータをPDFから抽出します。
Play framework 2.0.8のプロジェクトに追加しようとしたのですが、最新の5.5を追加しようとするとエラーが出てしまいます。
Playのバージョンが古すぎるのが悪いんでしょうが、仕方なく5.4を追加することに。
抽出時の動作は、TextExtractionStrategyによって規定されます。
上の例で利用している、SimpleTextExtractionStrategyは、PDFファイルに「スペースがないことがある」ことから、文字サイズを計算して、文字間にある程度の距離がある場合には自動でスペースを挿入するという処理をしているようです。
ところで、どういうわけかiTextpdfは日本語の文字サイズを常に0と認識してしまうようで、文字サイズと文字間距離とを比較すると、日本語ファイルの場合常に文字間距離が文字サイズに比べて大きいと誤認してしまうようです。
そのため、日本語ファイルの場合、スペースがほとんどの文字間に挿入されてしまい、上の問題が発生していたわけです。
そこで、これに対応できるStrategyを作る必要がある・・・んですが、日本語の文字サイズを計算する方法がとりあえずわかりませせん。
仕方ないので、LocationTextExtractionStrategyを継承したクラスに、応急措置的な処理を記述して対応しました。
JapaneseTextExtractionStrategy.scala
※利用するPDFによってisChunkAtWordBoundaryの内容は変更する必要があるとは思います。
iText, Programmable PDF software | iText Software
これを利用して、テキストデータをPDFから抽出します。
1.import
依存関係にiTextpdfを追加します。Play framework 2.0.8のプロジェクトに追加しようとしたのですが、最新の5.5を追加しようとするとエラーが出てしまいます。
Playのバージョンが古すぎるのが悪いんでしょうが、仕方なく5.4を追加することに。
"com.itextpdf" % "itextpdf" % "5.4.5"また、標準のパッケージには日本語フォントが入っておらず、日本語を扱うには追加パッケージのiText-asianも追加する必要があります。
"com.itextpdf" % "itext-asian" % "5.2.0"
2.文字列抽出処理の作成
文字列の抽出には、PdfReaderContentParser(またはPdfTextExtractor)を利用します。
val reader = new PdfReader("/xxx/yyy/test.pdf") val parser = new PdfReaderContentParser(reader) var result = "" for (i <- 1 to reader.getNumberOfPages()) { val st = parser.processContent(i, new SimpleTextExtractionStrategy) result += st.getResultantText() } reader.close()これでPDFからテキストデータが出力できる・・・かとおもいきや、日本語のPDFファイルを指定すると、無意味なスペースが挿入されてしまいます。
3.TextExtractionStrategyの作成
日本語のPDFファイルからのテキストの抽出時にスペースが混入してしまう問題は、SimpleTextExtractionStrategyに由来します。抽出時の動作は、TextExtractionStrategyによって規定されます。
上の例で利用している、SimpleTextExtractionStrategyは、PDFファイルに「スペースがないことがある」ことから、文字サイズを計算して、文字間にある程度の距離がある場合には自動でスペースを挿入するという処理をしているようです。
ところで、どういうわけかiTextpdfは日本語の文字サイズを常に0と認識してしまうようで、文字サイズと文字間距離とを比較すると、日本語ファイルの場合常に文字間距離が文字サイズに比べて大きいと誤認してしまうようです。
そのため、日本語ファイルの場合、スペースがほとんどの文字間に挿入されてしまい、上の問題が発生していたわけです。
そこで、これに対応できるStrategyを作る必要がある・・・んですが、日本語の文字サイズを計算する方法がとりあえずわかりませせん。
仕方ないので、LocationTextExtractionStrategyを継承したクラスに、応急措置的な処理を記述して対応しました。
JapaneseTextExtractionStrategy.scala
class JapaneseTextExtractionStrategy extends LocationTextExtractionStrategy { import LocationTextExtractionStrategy._ override def isChunkAtWordBoundary(chunk: TextChunk, previousChunk: TextChunk): Boolean = return chunk.distanceFromEndOf(previousChunk) > 10 }で、本体
val reader = new PdfReader("/xxx/yyy/test.pdf") val parser = new PdfReaderContentParser(reader) var result = "" for (i <- 1 to reader.getNumberOfPages()) { val st = parser.processContent(i, new JapaneseTextExtractionStrategy) result += st.getResultantText() } reader.close()これで適切にスペースが処理されるようになりました。
※利用するPDFによってisChunkAtWordBoundaryの内容は変更する必要があるとは思います。
コメント
0 件のコメント :
コメントを投稿