Python PDFから表を取り出しEXCELファイルに保存する方法(tabula-py)
お客様から送られてきたPDFに表が含まれているがうまく取り出すことができないのでそのまま手動でEXCELファイルに打ち直しているという人はいませんか?Pythonのライブラリを利用することでPDFに表示されている表からデータを取りだすことができます。また取り出したデータをEXCELファイルに表データとして保存することができます。プログラムで実装できると効率化だけではなく打ち間違いもなくなり安心して業務を行うことができます。
pypdfの利用した場合
pypdfは結合、分割などのPDFを操作する際に活用できるライブラリです。
pypdfにもPDFファイルからテキストを取得することができるのでpypdfを利用してPDFファイル内のテキストを取得してみましょう。
利用するPDFは下記のものでEXCELから作成したものです。ファイル名はsales.pdfとしてPythonコードを記述するファイルと同じディレクトリに保存します。
pypdfはpipを利用してインストールを行います。
% pip install pypdf
Collecting pypdf
Downloading pypdf-3.17.2-py3-none-any.whl.metadata (7.5 kB)
Downloading pypdf-3.17.2-py3-none-any.whl (277 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 277.9/277.9 kB 2.1 MB/s eta 0:00:00
Installing collected packages: pypdf
Successfully installed pypdf-3.17.2
pip listでインストールしたpypdfのバージョンを確認することができます。
% pip list
Package Version
--------------- ------------
pypdf 3.17.2
・
・
任意のディレクトリにtest.pyファイルを作成して以下のコードを記述します。sales.pdf
from pypdf import PdfReader
reader = PdfReader("sales.pdf")
page = reader.pages[0]
print(page.extract_text())
作成したtest.pyファイルを実行するとPDFファイルに記述されていた内容がそのままターミナルに表示されます。
python test.py
2023/12/13
今月の売上
日付 販売数備考
12023/9/1 100
22023/9/2 40
32023/9/3 32
42023/9/4 487
52023/9/5 2
62023/9/6 38
テキストがそのまま表示されるのでデータ間の区切りがないためそのままEXCELに保存してもテーブルとして表示させることができません。
今回は比較的綺麗に上から順番にテキストを取得することができましたがPDFによっては行毎に取得できなかったりするのでpypdfではうまく処理を行うことができません。
pypdfでは表のデータをうまく取得できないことがありますが表ではなく文字列で構成されたPDFファイルから文字列のみ取得する際には活用することができます。
tabulaを利用した場合
本文書の本題であるPDFの内部にある表を取得することに特化したライブラリtabulaを利用して動作確認を行います。tabulaを利用するために手元にPCにJavaをインストールする必要があるのでJavaを追加したくない場合やできない場合には利用することができません。
pipを利用してtabula-pyをインストールします。下記ではjpypeも一緒にインストールします。tabula-pyのみ指定してインストールした場合でも後ほどtabula.read_pdfを実行するとjpypeに関するエラーが表示されるのでjpypeを追加でインストールすることになります。
% pip install tabula-py[jpype]
pip listコマンドでインストールされたライブラリのバージョンを確認します。
% pip list
Package Version
--------------- ------------
distro 1.8.0
JPype1 1.4.1
numpy 1.26.2
packaging 23.2
pandas 2.1.4
pip 23.3.1
python-dateutil 2.8.2
pytz 2023.3.post1
setuptools 65.5.0
six 1.16.0
tabula-py 2.9.0
tzdata 2023.3
インストールしたtabulaを利用してPDFを読み込みます。
import tabula
df = tabula.read_pdf("sales.pdf", pages="all")
print(df)
実行するとJAVA_NOT_FOUND_ERRORのエラーとなりJavaが必要であることがわかります。
% python test.py
//略
raise JavaNotFoundError(JAVA_NOT_FOUND_ERROR)
tabula.errors.JavaNotFoundError: `java` command is not found from this Python process.Please ensure Java is installed and PATH is set for `java`
Javaのインストール
Javaのインストールを行うためにhttps://www.oracle.com/jp/java/technologies/downloads/を開きます。
スクロールするとOS選択のタブが表示されます。本文書ではWindowsを利用しているのでx64 MSI Installのリンクをクリックします。
クリックするとダウンロードが開始されるのでインストールを行ってください。
インストールが完了してjava -versionを実行するとインストールしたJavaのバージョンを確認することができます。
% java -version
java version "21.0.1" 2023-10-17 LTS
Java(TM) SE Runtime Environment (build 21.0.1+12-LTS-29)
Java HotSpot(TM) 64-Bit Server VM (build 21.0.1+12-LTS-29, mixed mode, sharing)
JAVA_HOMEの設定
Javaのインストールが完了したので再度test.pyを実行すると環境変数のJAVA_HOMEの設定に関するエラーが発生します。
% python test.py
//
raise JVMNotFoundException("No JVM shared library file ({0}) "
jpype._jvmfinder.JVMNotFoundException: No JVM shared library file (jvm.dll) found. Try setting up the JAVA_HOME environment variable properly.
Windows画面の検索バーに環境変数を入力して検索を行いユーザの環境変数にJAVA_HOMEを追加してください。追加する値はJavaのバージョンによって異なります。
JAVA_HOMEを設定後に再度実行するとPDFのテーブルの内容を取得することができます。テーブル以外のテキストの文字列は無視されます。
% python test.py
12月 13, 2023 2:09:32 午後 org.apache.fontbox.ttf.CmapSubtable processSubtype14
警告: Format 14 cmap table is not supported and will be ignored
12月 13, 2023 2:09:32 午後 org.apache.fontbox.ttf.CmapSubtable processSubtype14
警告: Format 14 cmap table is not supported and will be ignored
[ Unnamed: 0 日付 販売数 備考
0 1 2023/9/1 100 NaN
1 2 2023/9/2 40 NaN
2 3 2023/9/3 32 NaN
3 4 2023/9/4 487 NaN
4 5 2023/9/5 2 NaN
5 6 2023/9/6 38 NaN]
EXCELファイルへの保存
tabula.read_pdfで戻される型を確認しておきます。
import tabula
df = tabula.read_pdf("sales.pdf", pages="all")
print(type(df))
実行するとlistであることがわかります。複数の表がある場合はリストとして保存されます。
<class 'list'>
listの0番目に保存されているのでdf[0]でテーブルをDataFrameとして取得することができます。
DataFrameなのでto_excelでEXCELファイルに保存することができます。index=Falseを設定することでindexをEXCELに保存しないようにすることができます。
import tabula
df = tabula.read_pdf("sales.pdf", pages="all")
df[0].to_excel("sales.xlsx",index=False)
上記の例ではシンプルなデータでしたがヘッダーの文字に改行がある場合に綺麗に表が取得できない場合があります。特にセルを分ける線がある場合はオプションの”lattice=True”に設定することで綺麗に取得することができます。
import tabula
df = tabula.read_pdf("sales.pdf", lattice=True, pages="all")
df[0].to_excel("sales.xlsx",index=False)
tabulaを利用した場合はJavaのインストールなど他のライブラリに比べて利用するまでに手間がかかりますが利用すればPDFから簡単に表を取得してEXCELファイルに保存することができます。