目次
- PDF形式のデータから、テキストを抜き出す
- シンプルなレイアウトのPDFで試す
- 2段組みの複雑なPDFで試す
- 結論:プログラムのインプットにPDFは不適
- 理由1:うまくいくPDFとうまくいかないPDFがある
- 理由2:特にうざい2バイト文字が化ける問題
PDF形式のデータから、テキストを抜き出す
PDF形式のデータから、テキストを抜き出して、何か処理する時のインプットデータにできないかと試してみた結果のご報告です。
一口にPDFと言っても、様々なバージョンがあります。
暗号化もできます。
そいういうバリエーションを吸収しないといけないなどと考えると、プログラミングでデータで使うにはあまりに面倒な形式で、ライブラリなしでやる気にはなりません。
Pythonで使えるPDFライブラリ比較
Pythonで使える、PDFを扱えるライブラリをあたります。
pipでPDFをキーワードで検索すると、htmlをPDFに変換するとか、Markdown形式ファイルをPDF化するなど、特定の用途に適したものがいっぱいあります。
テキストを抽出する用途で探すと、「pdfminer」が、かんたんにつかえて、テキスト抽出の精度も高いと、口コミ評価が高かったので、これで試してみます。
pdfminerと一口に言っても、種類があります。
pip search pdfminer で探すと、3つのバージョンがでてきます。
- pdfminer / python2.xx系
- pdfminer3k / python3.xx系
- pdfminer.six / python2/3系共通
現在でも更新されているのは「pdfminer.six」だけみたいです。
python2と3でコンパチブルなのも、pdfminer.sixだけですし、これを使わない理由が見当たりません。
pdfminer.six
pdfminer.sixをインストールします。
pip install pdfminer.six
pdfminer.six付属のツールpdf2txt.py
pdfminer.sixには、pdf2txt.py というツールが付属してます。
インストールが正常に終了していれば、anacondaをインストールしたフォルダ(activateして仮想環境にしている場合はenvsの仮想環境名フォルダの下)のScriptsフォルダにインストールされてます。
Linux環境なら、パスが通っているのでそのまま実行できます。
でも、windowsでは無理なので、カレントフォルダにコピーして使います。
サンプルにするPDFは、こういうものにします。
これを「sample.pdf」として保存して、作業フォルダに置き、同じところに「pdf2txt.py」をコピーして、以下のようにします。
python pdf2txt.py sample.pdf
抽出されたテキストはこんな感じでした。
キーワー ド:ビ ッグファイブパーソナリテ ィ 質問紙法 尺度構成 , 信頼性, 妥当性
問題
Openness to Experience (Openness; 開放性)で
ある 。
近年のパーソナリティ特性論において, もっと
日本における語裳研究は背木 ( 1971 ) の先駆的
も確固たる 知 見を積み重ねているのは. Big Five
な研究に始まり,その後も継続的に行われている
( ビッグファイブ; Goldberg, 1990, 1992 ) や Five
(柏木・辻・藤島・山田 2005 ;柏木 ・和田・ 青
Factor Model ( 5 因 子モデル; ~、1cCrae & Costa,
木 , 1993; 村 上, 2003; 和田, 1996 ) 。 また , 日
1987 ) である 。
化けたりはしてませんが、改行や空白がランダムにはいっています。
付属ツールといえど、2段組みだとこうなってしまうようです。
pdfminerを使ったPythonプログラム
今度は、pdfminerを使ってテキストを抽出するpythonプログラムを書きます。
(Python3.7、3.8、3.9で動作確認しています。)
gettext() という名前のメソッドにしました。
# -*- coding: utf-8 -*- from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfpage import PDFPage from io import StringIO import re def gettext(pdfname): # PDFファイル名が未指定の場合は、空文字列を返して終了 if (pdfname == ''): return '' else: # 処理するPDFファイルを開く/開けなければ try: fp = open(pdfname, 'rb') except: return '' # リソースマネージャインスタンス rsrcmgr = PDFResourceManager() # 出力先インスタンス outfp = StringIO() # パラメータインスタンス laparams = LAParams() # 縦書き文字を横並びで出力する laparams.detect_vertical = True # デバイスの初期化 device = TextConverter(rsrcmgr, outfp, codec='utf-8', laparams=laparams) # テキスト抽出インタプリタインスタンス interpreter = PDFPageInterpreter(rsrcmgr, device) # 対象ページを読み、テキスト抽出する。(maxpages:0は全ページ) for page in PDFPage.get_pages(fp, pagenos=None, maxpages=0, password=None,caching=True, check_extractable=True): interpreter.process_page(page) #取得したテキストをすべて読みだす ret = outfp.getvalue() # 後始末をしておく fp.close() device.close() outfp.close() # 空白と改行をとりさり一塊のテキストとして返す return re.sub(r"\s| ",'',ret)
テキスト出力を、上記のメソッドを使ってやる場合はこうします。
import pdf2text as pt ret = pt.gettext('C:\\myWork\\00_python\\workspace\\src\\proc\\sample.pdf') print(ret)
シンプルなレイアウトのPDFで試す
最初にシンプルなPDFを処理してみます。
これから抜き取ったテキストは以下のとおりです。
マンション標準管理規約(団地型)○○団地管理規約第1章総則(目的)第1条この規約は、○○団地の管理又は使用に関する事項等について定めることにより、団地建物所有者の共同の利益を増進し、良好な住環境を確保することを目的とする。(定義)第2条この規約において、次に掲げる用語の意義は、それぞれ当該各号に定めるところによる。一区分所有権建物の区分所有等に関する法律(昭和37年法律第69号。以下「区分所有法」という。)第2条第1項の区分所有権をいう。二区分所有者区分所有法第2条第2項の区分所有者をいう。三団地建物所有者区分所有法第65条の団地建物所有者をいう。四占有者区分所有法第6条第3項の占有者をいう。五専有部分区分所有法第2条第3項の専有部分をいう。
シンプルなPDFなら、きれいにテキストが抜き取れているようです。
2段組みの複雑なPDFで試す
今度は、PDFを2段組のちょっと複雑なものに適用してみます。
付属ツールの出力に使ったものと同じものをやってみます。
出力結果です。
キーワード:ビッグファイブパーソナリティ質問紙法尺度構成,信頼性,妥当性問題OpennesstoExperience(Openness;開放性)である。近年のパーソナリティ特性論において,もっと日本における語裳研究は背木(1971)の先駆的も確固たる知見を積み重ねているのは.BigFiveな研究に始まり,その後も継続的に行われている(ビッグファイブ;Goldberg,1990,1992)やFive(柏木・辻・藤島・山田2005;柏木・和田・青Model(5因子モデル;~、1cCrae&Costa,rotcaF木,1993;村上,2003;和田,1996)。また,日1987)である。
二段組の処理ができてなくて、左と右の文章が混じってしまってます。
やはり、段組みとかの複雑な構造を認識して、文章としてとりだすのは難しいです。
結論:プログラムのインプットにPDFは不適
個人的な結論を言えば。
プログラム他で 加工や解析をするインプットデータとして受け取る形式としては、PDFファイルは適切ではない。
です。
PDFからのテキストの抜き出しは、「やってみないと、上手く行くかどうかわからない」うえに、「うまくいくもの」「うまくいかないもの」の事前の見極めが単純にいかず、結果見てびっくりになりやすいからです。
理由1:うまくいくPDFとうまくいかないPDFがある
上記のpythonプログラムで色々なPDFファイルから、テキストを抽出してみました。
うまく行ったものは、もちろんありました。
しかし、自分の手持ちのPDFだと、うまくいかないものも多かったです。
うまくいかなかったパターンは。
- テキストに見えていても画像がはりついていて、抽出できない。
- ファイルが暗号化されていて読めない。
- 読めて、テキストが抽出できても、2バイト文字が化ける。
などなど。
理由2:特にうざい2バイト文字が化ける問題
特に最後の文字化けはかなりうざいです。
PDFで見ていると同じように見えるのに、テキストを抽出してみると、例えば、以下のように表示されたりします。
以下は青空文庫の芥川龍之介のクモの糸の最初のほうですが、こんな風になってしまいました。
蜘蛛(cid:12506)糸芥川龍之介(cid:13268)(cid:10187)(cid:13269)(cid:13268)(cid:10186)(cid:13269)一(cid:12680)(cid:12695)(cid:12765)(cid:12681)(cid:12693)(cid:12734)
(cid:12506)というのはアドビ社のCIDフォントに割り振られている番号です。
まあ、それがそのまま出力されている=一致する2バイト文字を見つけられなかった・・ということなのでしょうが、事前に予想ができないので、後でプログラムで処理してたら異常終了して・・とか、ダメージうけそうです。
ではでは。