PythonでPDFからテキストを抽出する方法

PythonでPDFからテキストを抽出する方法

0.English sample

Extract text from PDF using Python.
https://github.com/patch0000/Python3-PDF2TXT-sample

1.pythonでPDFからテキストを抽出する方法まとめ

・PythonでクロールしたPDFファイルからpdfminerでテキストを抽出する方法
・PDFPage.create_pagesとPDFPage.get_pagesを使う方法があるが汎用性を持たせられない
・PDFは文書によって構造が異なるのでサンプルを参考にしつつ構造決め打ちが楽かも

2.実行した事

Anaconda3-5.0.1-Windows-x86.exeをインストールして実行。
Pythonには環境構築ツールやパッケージ管理ツールが多数あり他にもっと良い方法があるかもしれないが、上記はnumpy,scipy,scikit-learn,matplotlib,skimageなど、機械学習に必要なモジュールが一通り揃っており且つSpyderと言う出来の良い統合開発環境が揃っているので気軽に始められるのが利点。

個人的には何事もシンプルなUnix環境でviで書くのも嫌いではないが、画像処理は処理結果をすぐ表示したくなるのでSpyderが楽なのだ。

ただし、PDFを取り扱うモジュールであるpdfminerはディフォルトでは入っていないので改めてcondaでインストールする必要がある。(Spyder環境ではpipは使うと不具合が出てしまうらしいのでNG)

2018年1月、現在、pdfminerは4種類ある模様
pdfminer python2.x系用のライブラリ、オリジナルで作者様は日本人っぽい
pdfminer.six python2.x系と3.x系両用のライブラリ
pdfminer3k python3.x系用のライブラリ
pdfminer2 python2.x系と3.x系両用らしいが導入が大変そう

当初は下記のように考えた。

pdfminer.sixが一番更新頻度も高く良さそうだが、sixと言うpython2.xとpython3.x両方でpythonスクリプトを動かすためのモジュールを使っていてやや独特な記法になるようだ。本題ではないsixの使い方を間違ってハマルと困るのでpdfminer3kにしよう!

しかし、非常に厄介なのがpythonにimportして使うときの名前が全部「pdfminer」になっている事。ネット上のサンプルコードやQAがどのpdfminerを前提にしているのか明示されていないケースも多くコピペ一発ではまず動かない。

思った以上にpdfminer3kの導入でトラブったのでpdfminer.sixを使う事にした。文末に参考情報としてpdfminerとpdfminer3k,pdfminer.sixの違いを把握できた限りで書いておく。

pdfminer.sixはAnacondaには含まれていないのでパッケージ管理ツールcondaを使ってインストールしないといけない。

なお、モジュール同士の依存関係などを解決するため、かなりたくさんの関連モジュールのインストールが必要になるケースがあり、運が悪いとタイムアウトしまくってインストールに失敗するので先に下記コマンドで
タイムアウト時間を伸ばした方が良い。

スタートメニューよりAnaconda Promptを立ち上げて
conda config –show
conda config –set remote_read_timeout_secs 6000
conda config –show

pdfminer.sixのインストールは下記
conda install -c conda-forge pdfminer.six
大量のパッケージのアップデートや置き換えが必要だがやって良いか?と問われるので「y」を入力してかなり待つ。

かなり時間がかかり場合によってはリトライする必要があるがインストール完了

スクリプト自体はオリジナルサイトの文章構造を見つつ、先人サイト様のコードを参考にすると意外にあっさり動くのだが・・・

先達のコードを参考にするに2つのやり方があって、

1)PDFPage.create_pagesを使うパターン
抽出しきれない文章がある。私が遭遇したPDFではTextBox系を使わずにLTFigure配下にLTCharとして一文字ずつ格納されていたパターンだった。現状、様々なテストケース(つまりPDF)を作ってテストする事が難しいので汎用的に動くスクリプトを作る事は難しそう。特定のPDFの構造を決め打ちして抽出する事を目指すのが現実的に思う。下記にサンプルコードを上げました。ご参考までに。

https://github.com/patch0000/Python3-PDF2TXT-sample

2)PDFPage.get_pagesを使うパターン
一気にテキストが出てきてしまい、ページ区切りさえわからなくなってしまう。また、英文のPDFの場合、単語間のスペースが消えてしまうケースがある。特に問題が発生しないPDFもあるようだが、確実に問題が発生するPDFもある。

 

3.参考)pdfminerとpdfminer3k,pdfminer.sixの違い

1.モジュールのツリー構造
pdfminer,pdfminer.sixとpdfminer3kはクラスの配置位置が異なるようで、ネット上のサンプルコードを動かすとimport文で
「ImportError: cannot import name ‘PDFPage’」等々のエラーがでるケースがある。

なお、下記テストスクリプトでpythonの外部モジュールの関数(クラス)一覧を表示できる。

import pdfminer
print(dir(pdfminer))
print(“—————————————-“)
print(dir(pdfminer.pdfparser))

2.関数のキーワード引数やメソッド、アトリビュート
pdfminer2とpdfminer.sixでは関数にキーワード引数が設定されているが、pdfminer3kは一部されていないようだ。

TextConverter(rsrcmgr, rettxt, codec=’utf-8’, laparams=laparams)
のような書き方だと
「TypeError: __init__() got an unexpected keyword argument ‘codec’」
とエラーになる。下記だと一応、エラーにはならないが・・・
TextConverter(rsrcmgr, rettxt, ‘utf-8’, laparams=laparams)

しかし、codecが意識されていないとしたら日本語の取り扱いで確実にトラブりそうなのでこの時点でpdfminer3kは断念。

更に余談だが、pdfminer.sixをインストール、pdfminer3kをアンインストールしたら
「ModuleNotFoundError: No module named ‘PDFParser’」と、
ついさっきまで問題なくうごいていたのにモジュールが見つからないと出るようになった。

どうもモジュールサーチパスが破壊されたようでpythonを再インストールするハメになった。先にpdfminer3kをアンインストールするべきだったのかもしれないが、要注意。

なお、WebBigDataではクローラーの作成、ビッグデータの収集代行も承っております。

4.参考サイト

(1)PDFMiner homepage
Programming with PDFMiner

(2)ながいものには、まかれたくない
厚生労働省のブラック企業リストをPythonで解析する(PDFMiner.six)

(3)いるかのボックス
Python3でPDFのテキストを抽出する