⇧ 板って...
皆さ~ん、PDF使ってますか~?
Portable Document Format(ポータブル・ドキュメント・フォーマット、略称:PDF)は、アドビシステムズが開発および提唱する、電子上の文書に関するファイルフォーマットである。1993年に発売されたAdobe Acrobatで採用された。
⇧ Adobeが発祥だったとは知らなんだ。
特定の環境に左右されずに全ての環境でほぼ同様の状態で文章や画像等を閲覧できる特性を持っている。
⇧ どんな端末でもOKですと。
アドビシステムズはPDF仕様を1993年より無償で公開していたが、それでもPDF規格はAdobeが策定するプロプライエタリなフォーマットであった。2008年7月には国際標準化機構によってISO 32000-1として標準化された。
⇧ 15年間、標準化されなかったって...飛びぬけた技術だったってことかしら?
アドビはISO 32000-1 についての特許を無償で利用できるようにしたが、XFA (Adobe XML Forms Architecture) やAdobe JavaScriptなどはアドビのプロプライエタリな部分として残っている。
⇧太っ腹っすね。
PDFをオフラインで確認するときに良く使うのが、
標準の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には制限あるそうな。
ちなみに、
⇧ Windows版の「Adobe Acrobat Reader DC」のインストールに必要なシステムに「Internet Explorer 11」となっているのが何とも...
で、みんな大好きPDFですが、テキストとかを抽出したいと思うことあるあるだよね?
そんな時に使えるのが、 「tabula」ですと。
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」ってプロジェクトのほうは有志の人たちでメンテナンス続けていくかも、的な状況らしい。
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」と全く同じ字面ってのが、なかなかインパクトありますな。
tabula-java を使ってみる
何か、
⇧ Pythonでラップしたものが、こちら、みたいな感じで、一旦、多言語に変換して使うってのが一般的なんですかね?
同様の疑問を抱いた人がおられたようです。
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.
⇧ まぁ、普通思うよね、tabula-Javaって言ってんのに、なんで「Python」「R」「PHP」で使う例はあるのに、「Java」で使う例が無いんだと。
Stack Overflowに記載されている方法で、Javaで使えるのか試してみることに。
今回は、ビルドツールとして、「Maven」を使うことにします。
Eclipseを起動して、「ファイル(F)」>「Mavenプロジェクト」。
デフォルトの設定状態で「次へ(N)」押下しました。このあたりはご自分の参画してるプロジェクトの環境に合わせるで。
同じく、デフォルトの設定状態で「次へ(N)」押下しました。このあたりはご自分の参画してるプロジェクトの環境に合わせるで。
「グループ Id」「アーティファクト Id」は適当に決めて「完了(F)」押下。このあたりはご自分の参画してるプロジェクトの環境に合わせるで。
プロジェクトが作成されました。
⇧ 「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」フォルダ作られんらしい、たぶん...
何故ならば、
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」を作っていこうかと。
「src/main/resources」フォルダ作成されました。
Eclipseの表示で「.classpath」ファイルが見えなくなってるので、
上記のボタンをクリックし、「フィルターおよびカスタマイズ(F)...」で、
「.*リソース」が隠れる設定になってしまっているので、
チェックを外します。で「OK」。
そうすると、「.classpath」が表示されるので、編集します。
「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>
ちなみに、
画面を拝見したところ、src/main/resources以下が通常のフォルダアイコンになっていましたので、Javaのクラスパスから除外された設定です。
ビルドパス>ビルドパスの構成を開き、src/main/resourcesの除外設定に ** がなされていると、同様の現象、実行可能jarでエクスポートした際にビルドパスに含まれません。
この設定を除外すると、実行可能jarに含まれます。
⇧ 本番環境を想定する場合は、「除外設定」は行わないほうが良いんですかね?
まぁ、PDFファイルを配置するフォルダを作成しますか。
「file」フォルダが作成できたら、適当なPDFファイルをドラッグアンドドロップで。
「ファイルをコピー(C)」で「OK」押下。
PDFファイルの中身は、以下のような月の稼働時間って感じの表です。
⇧ 何か、真ん中の表(「名前」とかのある表)の最後に空白行を入れないと、タブの挿入が最後の方でおかしくなったのがよく分からん...
「tabula-java」って結構、デリケートなのかもね...
そんでは、Javaで取得できるか試してみますが、ソースコードで警告が出てしまうんよね。
「RectangularTextContainer は raw 型です。総称型 RectangularTextContainer<T> への参照は、パラメーター化する必要があります」って怒られるんだけど、package technology.tabulaのTable.class の getRows メソッドが、
public List<List<RectangularTextContainer>> getRows()
だしな~、戻り値が決まっっちゃってるしな~。
⇧ 一応、「@SuppressWarnings("rawtypes")」とか追加すれば警告は消えるけども...
⇧ あとは、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(); } } } }
で、実行してみる。
⇧ むっちゃ崩れとるやんけ~!って感じなんですが、これを、LibreOffice Calc(Excelでも変わらんと思うが)に貼り付けると、
整いました~、という感じで、PDFの内容が表の形のまま?抽出できるみたいです。
環境依存の文字である①とかが、普通の 1 になっちゃったりしてるけど...。
PDFの種類にもよるとは思いますが、使える状況なら使っていきたいところですね。
2020年9月9日(水)追記:↓ ここから
う~ん、テキストのコピペができないPDFで試したところ、何も抽出できなかったというね...
◆読み取り保護
PDFファイルの中には内容が保護されているものが存在します。テキスト自体は正しく表示されていても、テキストをコピーしようとすると「Copying text was denied (テキストのコピーが拒否されました)」といった内容が表示され、テキストの抽出ができないようになっています。
なぜコピーができないのかというと、PDFファイルに、テキストのコピーを許可するかどうかを決める「アクセス許可」の設定がされているためです。この設定によって、PDFは問題なく表示されていても、PDFビューアーがテキストのコピーを禁止してしまいます。
⇧ おそらく、読み取り保護ってものが設定されてるPDFだったんでしょうね。
このあたりの設定が解除ができれば、抽出できるのかは分からんけど、PDFから情報を抽出したいことって結構あるあるだとは思うんだけどな~。
一応、
⇧ ブラウザのChromeを使えば、「読み取り保護」を解除できるらしいけど、許容してくれる現場かどうかが鍵ですかね?
2020年9月9日(水)追記:↑ ここまで
2020年10月11日(日)追記:↓ ここから
なんと、
⇧ 混在してる場合があり、
Tabula が読み込めるDPFはテキストデータを含むものだけで、画像をスキャンして作ったPDFは対応できない。
⇧ 「画像」をスキャンして作ったPDFは読み込んでくれないんだって...
PDFのどの部分が「画像」なのかとか分からんと判断の仕様が無いんだが...
って思ったら、PDFを開いて、テキストで検索できれば、画像じゃないってことらしい。
⇧ 確かに、下の表は画像なんだけど、テキストの検索でヒットしなかった。
ただ、
PDFで文字が検索できないのは、スキャナーを使用して保存した画像でPDF内部に文字コードがない場合、フォント埋め込みしたPDFでPDFから正しい文字コードが取得できない場合、フォントがアウトライン化されてしまっている場合、などが考えられます。
⇧「画像」じゃない場合でも検索できない時もあるそうな...。
「画像」の場合は、OCR(Optical Character Recognition) とかで処理するしかないんだろうけど、ってことで試してみたけど、
⇧ ズタボロでしたけどね...
PDF の扱いって厄介だな...
2020年10月11日(日)追記:↑ ここまで
今回はこのへんで。