tabula ならPDFの内容を表の形のまま抽出できるみたい

f:id:ts0818:20200904145709j:plain

Tabula - を意味するラテン語テーブル (家具)の「語源」の項目も参照のこと。

タブラ (曖昧さ回避) - Wikipedia

⇧ 板って...

 

皆さ~ん、PDF使ってますか~?

Portable Document Format(ポータブル・ドキュメント・フォーマット、略称:PDF)は、アドビシステムズが開発および提唱する、電子上の文書に関するファイルフォーマットである。1993年に発売されたAdobe Acrobatで採用された。

Portable Document Format - Wikipedia

Adobeが発祥だったとは知らなんだ。 

特定の環境に左右されずに全ての環境でほぼ同様の状態で文章や画像等を閲覧できる特性を持っている。

Portable Document Format - Wikipedia

⇧ どんな端末でもOKですと。

アドビシステムズはPDF仕様を1993年より無償で公開していたが、それでもPDF規格はAdobeが策定するプロプライエタリなフォーマットであった。2008年7月には国際標準化機構によってISO 32000-1として標準化された

Portable Document Format - Wikipedia

⇧ 15年間、標準化されなかったって...飛びぬけた技術だったってことかしら?

アドビはISO 32000-1 についての特許を無償で利用できるようにしたが、XFA英語版 (Adobe XML Forms Architecture) やAdobe JavaScriptなどはアドビのプロプライエタリな部分として残っている。

Portable Document Format - Wikipedia

⇧太っ腹っすね。

 

PDFをオフラインで確認するときに良く使うのが、

www.itmedia.co.jp

 標準のPDFビュワーは名実ともに「Acrobat Reader DC」である。Acrobat Reader DCは無償配布されており、Adobe純正という安心感もあってシェアも大きい。企業、官公庁をはじめ、多くの人がAcrobat ReaderをPDFビュワーとして活用しているはずだ。

意外と知らないPDF作成の落とし穴 「Adobe Acrobat DC」を選ぶ5つの理由 (2/3) - ITmedia PC USER

 だが、実はAcrobat Readerが完全に保証するPDF生成アプリケーションはアドビ製品のみだ。サードパーティー製PDF生成ツールで作成したPDFも表示することはできるものの、もし表示に問題があったとしてもそれは全て「保証外」。契約書や企画書など大切な文書として取り扱うPDFだからこそ、予期せぬトラブルを回避するためにも、デファクトスタンダードとなっているAcrobat Readerで閲覧を保証されているAdobe Acrobat DCでPDFを作るべきだろう

意外と知らないPDF作成の落とし穴 「Adobe Acrobat DC」を選ぶ5つの理由 (2/3) - ITmedia PC USER

⇧ 「Adobe Acrobat Reader DC」ですが、表示できるPDFには制限あるそうな。

 

ちなみに、

helpx.adobe.com

Windows版の「Adobe Acrobat Reader DC」のインストールに必要なシステムに「Internet Explorer 11」となっているのが何とも...

 

で、みんな大好きPDFですが、テキストとかを抽出したいと思うことあるあるだよね?

そんな時に使えるのが、 「tabula」ですと。

github.com

Is tabula an active project?

Tabula is, and always has been, a volunteer-run project. We've ocassionally had funding for specific features, but it's never been a commercial undertaking. At the moment, none of the original authors have the time to actively work on the project. The end-user application, hosted on this repo, is unlikely to see updates from us in the near future. tabula-java sees updates and occasional bug-fix releases from time to time.

GitHub - tabulapdf/tabula: Tabula is a tool for liberating data tables trapped inside PDF files

⇧ 見つけたと思ったら、もうメンテナンス無理っすわって状態らしい...

Oh, my gosh...

で、これからは、「tabula-java」ってプロジェクトのほうは有志の人たちでメンテナンス続けていくかも、的な状況らしい。

github.com

tabula-java is a library for extracting tables from PDF files — it is the table extraction engine that powers Tabula (repo). You can use tabula-java as a command-line tool to programmatically extract tables from PDFs.

GitHub - tabulapdf/tabula-java: Extract tables from PDF files

⇧ 「Tabula」を強化した「テーブル抽出エンジン」になってるらしい。

 

ちなみに、

タブラ・ラーサラテン語tabula rasa)は、白紙状態の意。などを引いた書字版を取り消して何も書き込まれていない状態

タブラ・ラーサ - Wikipedia

⇧ の「tabula」と全く同じ字面ってのが、なかなかインパクトありますな。

 

tabula-java を使ってみる

何か、

qiita.com

Pythonでラップしたものが、こちら、みたいな感じで、一旦、多言語に変換して使うってのが一般的なんですかね?

 

同様の疑問を抱いた人がおられたようです。

stackoverflow.com

Tabula looks like a great tool for extracting tabular data from PDFs. There are plenty of examples of how to call it from the command line or use it in Python but there doesn't seem to be any documentation for use in Java. Does anyone have a worked example?

Note, tabula does provide source code but it seems confused between versions. For example, the example on GitHub references a TableExtractor class which does not seem to exist in the JAR.

https://github.com/tabulapdf/tabula-java

How can tabula (JAR) be called from Java? - Stack Overflow

⇧ まぁ、普通思うよね、tabula-Javaって言ってんのに、なんで「Python」「R」「PHP」で使う例はあるのに、「Java」で使う例が無いんだと。

 

Stack Overflowに記載されている方法で、Javaで使えるのか試してみることに。 

今回は、ビルドツールとして、「Maven」を使うことにします。

Eclipseを起動して、「ファイル(F)」>「Mavenプロジェクト」。

f:id:ts0818:20200904102912p:plain

デフォルトの設定状態で「次へ(N)」押下しました。このあたりはご自分の参画してるプロジェクトの環境に合わせるで。

f:id:ts0818:20200904103109p:plain

同じく、デフォルトの設定状態で「次へ(N)」押下しました。このあたりはご自分の参画してるプロジェクトの環境に合わせるで。

f:id:ts0818:20200904103148p:plain

「グループ Id」「アーティファクト Id」は適当に決めて「完了(F)」押下。このあたりはご自分の参画してるプロジェクトの環境に合わせるで。

f:id:ts0818:20200904103253p:plain

プロジェクトが作成されました。

f:id:ts0818:20200904103620p:plain

pom.xml に「tabula-java」を追加で。

mvnrepository.com

⇧ 「tabula」ってなってるけど、「tabula-java」ってことかと。
今回は、バージョン「1.0.4」を使うことにしました。

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example.tabula</groupId>
	<artifactId>tabula-project</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>tabula-project</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/technology.tabula/tabula -->
		<dependency>
			<groupId>technology.tabula</groupId>
			<artifactId>tabula</artifactId>
			<version>1.0.4</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

そして、なんか、Eclipseの「Mavenプロジェクト」作成時の「アーキタイプの選択」によっては、「src/main/resources」フォルダ作られんらしい、たぶん...

stackoverflow.com

 

何故ならば、

maven.apache.org

maven.apache.org

By default, Maven will look for your project's resources under src/main/resources.

Apache Maven Resources Plugin – Specifying resource directories

Maven の公式の見解だと、デフォルトで「src/main/resources」が作成されますってなってるしね、って言うか、Eclipseのお節介仕様ってことかい。

で、「src/main/resources」を後から追加するには、手動で作成して、「.classpath」ファイルに追加してやらにゃならんらしい...まじか。

なんで、作り直せるならプロジェクト再作成が手っ取り早いらしい、何だかな...

 

まぁ、今回は「src/main/resources」を作っていこうかと。 

f:id:ts0818:20200904114929p:plain

f:id:ts0818:20200904115029p:plain

「src/main/resources」フォルダ作成されました。 

f:id:ts0818:20200904115319p:plain

Eclipseの表示で「.classpath」ファイルが見えなくなってるので、

f:id:ts0818:20200904115830p:plain

上記のf:id:ts0818:20200904115905p:plainボタンをクリックし、「フィルターおよびカスタマイズ(F)...」で、

f:id:ts0818:20200904115739p:plain

「.*リソース」が隠れる設定になってしまっているので、

f:id:ts0818:20200904120028p:plain

チェックを外します。で「OK」。

f:id:ts0818:20200904120147p:plain

そうすると、「.classpath」が表示されるので、編集します。

f:id:ts0818:20200904120226p:plain

「src/main/resources」フォルダを作成すると、「.classpath」に以下の記載が追加されてるので、
 

	<classpathentry kind="src" path="src/main/resources"/>

 以下のように修正。ビルドツールにGradleとか使ってる場合は、また違ってくるかと。

 	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
 	       <attributes>
 	           <attribute name="maven.pomderived" value="true"/>
 	       </attributes>
 	</classpathentry>

 

ちなみに、

teratail.com

画面を拝見したところ、src/main/resources以下が通常のフォルダアイコンになっていましたので、Javaのクラスパスから除外された設定です。

ビルドパス>ビルドパスの構成を開き、src/main/resourcesの除外設定に ** がなされていると、同様の現象、実行可能jarでエクスポートした際にビルドパスに含まれません。
この設定を除外すると、実行可能jarに含まれます。

Java - Javaでresourcesに配置したテキストファイルがjar化すると読み込めません|teratail

⇧ 本番環境を想定する場合は、「除外設定」は行わないほうが良いんですかね?

 まぁ、PDFファイルを配置するフォルダを作成しますか。

f:id:ts0818:20200904123003p:plain

f:id:ts0818:20200904123040p:plain

f:id:ts0818:20200904123118p:plain

「file」フォルダが作成できたら、適当なPDFファイルをドラッグアンドドロップで。

f:id:ts0818:20200904123419p:plain

「ファイルをコピー(C)」で「OK」押下。

f:id:ts0818:20200904124249p:plain

 

PDFファイルの中身は、以下のような月の稼働時間って感じの表です。

f:id:ts0818:20200904144402p:plain

⇧ 何か、真ん中の表(「名前」とかのある表)の最後に空白行を入れないと、タブの挿入が最後の方でおかしくなったのがよく分からん...

「tabula-java」って結構、デリケートなのかもね...

そんでは、Javaで取得できるか試してみますが、ソースコードで警告が出てしまうんよね。

「RectangularTextContainer は raw 型です。総称型 RectangularTextContainer<T> への参照は、パラメーター化する必要があります」って怒られるんだけど、package technology.tabulaのTable.class の getRows メソッドが、

public List<List<RectangularTextContainer>> getRows()    

だしな~、戻り値が決まっっちゃってるしな~。

f:id:ts0818:20200904162433p:plain

⇧ 一応、「@SuppressWarnings("rawtypes")」とか追加すれば警告は消えるけども...

harikofu.blog.fc2.com

⇧ あとは、Eclipse側の設定で、警告を表示させない、みたいな方法もあるらしい、どっちにしろ根本的な解決にはなってないんだけどね...。

まぁ、警告が出たままでも実行には問題が無かったので、先に進みました。  

package com.example.tabula.tabula_project;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.apache.pdfbox.pdmodel.PDDocument;

import technology.tabula.ObjectExtractor;
import technology.tabula.Page;
import technology.tabula.RectangularTextContainer;
import technology.tabula.Table;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

/**
 * PDFの内容を抽出
 *
 */
public class App
{
  public static void main(String[] args) throws IOException {
    final String FILEPATH= "src/main/resources/file/";
    final String FILENAME="sample_8月次稼働.pdf";

    Path path = Paths.get(FILEPATH + FILENAME);
    PDDocument pd = PDDocument.load(path.toFile());

    int totalPages = pd.getNumberOfPages();
    System.out.println("Total Pages in Document: "+totalPages);

    ObjectExtractor oe = new ObjectExtractor(pd);
    SpreadsheetExtractionAlgorithm sea = new SpreadsheetExtractionAlgorithm();
    Page page = oe.extract(1);

    // extract text from the table after detecting
    List<Table> table = sea.extract(page);
    for(Table tables: table) {
      List<List<RectangularTextContainer>> rows = tables.getRows();

      for(int i=0; i<rows.size(); i++) {

        List<RectangularTextContainer> cells = rows.get(i);

        for(int j=0; j<cells.size(); j++) {
           System.out.print(cells.get(j).getText()+"\t");
        }
        System.out.println();
      }
    }
  }
}
    

で、実行してみる。

f:id:ts0818:20200904134222p:plain

f:id:ts0818:20200904143704p:plain

⇧ むっちゃ崩れとるやんけ~!って感じなんですが、これを、LibreOffice Calc(Excelでも変わらんと思うが)に貼り付けると、

f:id:ts0818:20200904143622p:plain

整いました~、という感じで、PDFの内容が表の形のまま?抽出できるみたいです。

環境依存の文字である①とかが、普通の 1 になっちゃったりしてるけど...。


PDFの種類にもよるとは思いますが、使える状況なら使っていきたいところですね。

2020年9月9日(水)追記:↓ ここから

う~ん、テキストのコピペができないPDFで試したところ、何も抽出できなかったというね...

gigazine.net

◆読み取り保護
PDFファイルの中には内容が保護されているものが存在します。テキスト自体は正しく表示されていても、テキストをコピーしようとすると「Copying text was denied (テキストのコピーが拒否されました)」といった内容が表示され、テキストの抽出ができないようになっています。

なぜコピーができないのかというと、PDFファイルに、テキストのコピーを許可するかどうかを決める「アクセス許可」の設定がされているためです。この設定によって、PDFは問題なく表示されていても、PDFビューアーがテキストのコピーを禁止してしまいます。

PDFからテキストを抽出するのはなぜ難しいのか? - GIGAZINE

⇧ おそらく、読み取り保護ってものが設定されてるPDFだったんでしょうね。

このあたりの設定が解除ができれば、抽出できるのかは分からんけど、PDFから情報を抽出したいことって結構あるあるだとは思うんだけどな~。

 

一応、

www.koikikukan.com

⇧ ブラウザのChromeを使えば、「読み取り保護」を解除できるらしいけど、許容してくれる現場かどうかが鍵ですかね?

2020年9月9日(水)追記:↑ ここまで

2020年10月11日(日)追記:↓ ここから

なんと、

PDF文書は1以上のページで構成され、各ページにはテキスト画像図形が含まれる。

Portable Document Format - Wikipedia

⇧ 混在してる場合があり、

qiita.com

Tabula が読み込めるDPFはテキストデータを含むものだけで、画像をスキャンして作ったPDFは対応できない。

PDFの表を表のまま読み取るには tabula - Qiita

⇧ 「画像」をスキャンして作ったPDFは読み込んでくれないんだって...

PDFのどの部分が「画像」なのかとか分からんと判断の仕様が無いんだが...

って思ったら、PDFを開いて、テキストで検索できれば、画像じゃないってことらしい。

f:id:ts0818:20201011225916p:plain

⇧ 確かに、下の表は画像なんだけど、テキストの検索でヒットしなかった。

ただ、

www.antenna.co.jp

PDFで文字が検索できないのは、スキャナーを使用して保存した画像でPDF内部に文字コードがない場合、フォント埋め込みしたPDFでPDFから正しい文字コードが取得できない場合、フォントがアウトライン化されてしまっている場合、などが考えられます。

これらのPDFを文字検索可能にする一般的な方法は、OCR光学文字認識)を使ってPDFに文字コードを追加することです。

PDFで文字が検索できないけど? 何が問題? どうしたら良い? | アンテナハウス PDF資料室

⇧「画像」じゃない場合でも検索できない時もあるそうな...。

「画像」の場合は、OCR(Optical Character Recognition) とかで処理するしかないんだろうけど、ってことで試してみたけど、

ts0818.hatenablog.com

⇧ ズタボロでしたけどね...

PDF の扱いって厄介だな... 

2020年10月11日(日)追記:↑ ここまで

今回はこのへんで。