【試してみた】PythonでPDFからテキストを抽出する方法

<h2>【はじめに】</h2>
<ul>
 	<li>仕事中にブログネタを思いつくことが時々あり、会社のPCをお借りしてテキストに起こすことがありました。</li>
 	<li>個人アドレスにはメールを送れないので、毎回プリントして帰宅後に自分のPCに転記するということをしています。</li>
 	<li>毎回この作業をすると思うとかなり面倒なので、Pythonを使ってテキストを抽出する方法を試してみました。</li>
</ul>
<h3>本記事の内容</h3>
<ul>
 	<li>準備</li>
 	<li>PDFファイルからテキストを抽出してみた</li>
 	<li>PDFファイルを画像として認識し、テキストを抽出してみた</li>
</ul>
※OS環境はMacOS、実行環境はJupyter Labを使用します。
<h2>【準備】</h2>
<h3>作業ディレクトリにテキスト抽出したいPDFファイルを配置する</h3>
<ul>
 	<li>sample1.pdf</li>
</ul>
<a href="https://gyazo.com/744f205730c9cf4ef00ec6dc101050ac"><img src="https://i.gyazo.com/744f205730c9cf4ef00ec6dc101050ac.png" alt="Image from Gyazo" /></a>
<ul>
 	<li>sample2.pdf</li>
</ul>
<a href="https://gyazo.com/ea35ef180ed60a1c948593479edbfc40"><img src="https://i.gyazo.com/ea35ef180ed60a1c948593479edbfc40.png" alt="Image from Gyazo" /></a>
<h2>【PDFファイルからテキストを抽出してみた】</h2>
<h3>pdfminer.sixをインストール</h3>
pdfminer.sixはPDFファイルからテキスト情報を抽出する機能を有するPythonモジュールです。

https://pdfminersix.readthedocs.io/en/latest/
<pre><code>!pip install pdfminer.six
</code></pre>
<a href="https://gyazo.com/1ea0e89ad7c368c5f1b3d7312f90e7b2"><img src="https://i.gyazo.com/1ea0e89ad7c368c5f1b3d7312f90e7b2.png" alt="Image from Gyazo" /></a>
<h3>ライブラリをインポート</h3>
<pre><code>import pdfminer
</code></pre>
<h3>pdfminer.sixのGitHubから公開されているコード「pdf2txt.py」を作業ディレクトリに持ってくる</h3>
GitHubにサンプルコードが公開されているため、今回はそのまま使用したいと思います。
同じ名前でファイルを作成し、コードをコピーすればOKです。

https://github.com/pdfminer/pdfminer.six/blob/master/tools/pdf2txt.py

<a href="https://gyazo.com/b22efb2e8ac67fd3e4b0187c1e0acd45"><img src="https://i.gyazo.com/b22efb2e8ac67fd3e4b0187c1e0acd45.png" alt="Image from Gyazo" /></a>
<h3>「pdf2txt.py」を実行して「sample1.pdf」のテキストを抽出する</h3>
<pre><code>!python pdf2txt.py sample1.pdf
</code></pre>
実行すると正しくテキスト抽出がされているみたいです。

<a href="https://gyazo.com/ebb485e74de3a56a3e497494808e0c43"><img src="https://i.gyazo.com/ebb485e74de3a56a3e497494808e0c43.png" alt="Image from Gyazo" /></a>
<h3>「sample2.pdf」のテキストを抽出する</h3>
次のように、実行結果に何も表示されませんでした。
一度出力した資料をスキャンでPDFファイルにした場合は、より高度なOCR処理が必要みたいです。

<a href="https://gyazo.com/d609e139cda077eef90311d67228f02a"><img src="https://i.gyazo.com/d609e139cda077eef90311d67228f02a.png" alt="Image from Gyazo" /></a>
<h3>ディレクトリとコード</h3>
今回のディレクトリ構成とコードをまとめるとこのような感じになります。

<a href="https://gyazo.com/1585f767432efd5e6958c810c5b767c2"><img src="https://i.gyazo.com/1585f767432efd5e6958c810c5b767c2.png" alt="Image from Gyazo" /></a>
<h2>【PDFファイルを画像として認識し、テキストを抽出してみた】</h2>
pdfminer.sixではPDFファイルによっては抽出できないものもありましたので、今回はPDFとしてではなく、画像として認識し文字を抽出できるかどうか試していきたいと思います。
<h3>PyOCRのインストール</h3>
「Pyocr」はPythonのOCRのライブラリで、Tesseract(OCRツール)を利用できます。
TesseractはGoogleが公開したOCRエンジンでGitから無料でダウンロードが可能で、Tesseractを利用することで画像に表示されている文字を抽出することが出来ます。
<pre><code>!pip install pyocr 
</code></pre>
<a href="https://gyazo.com/e4c02cfa28cfe6192287dc9480b7fb70"><img src="https://i.gyazo.com/e4c02cfa28cfe6192287dc9480b7fb70.png" alt="Image from Gyazo" /></a>
<h3>Tesseractのインストール</h3>
OCR engineである「Tesseract」をインストールします。
<pre><code>!brew install tesseract
</code></pre>
<a href="https://gyazo.com/d735d09154eb7de78f8019bb52788509"><img src="https://i.gyazo.com/d735d09154eb7de78f8019bb52788509.png" alt="Image from Gyazo" /></a>
<h3>pdf2imageのインストール</h3>
PDFを画像ファイルに変換してくれるライブラリ「pdf2image」をインストールします。
<pre><code>!pip install pdf2image
</code></pre>
<a href="https://gyazo.com/30645c1622b1fdfc96bc6a4e9583a125"><img src="https://i.gyazo.com/30645c1622b1fdfc96bc6a4e9583a125.png" alt="Image from Gyazo" /></a>
<h3>popplerのインストール</h3>
PDFドキュメントのレンダリングに利用されるライブラリ「poppler」をインストールします。
<pre><code>!brew install poppler
</code></pre>
<a href="https://gyazo.com/d741ad35a678b27cc281d7203b7bf3e5"><img src="https://i.gyazo.com/d741ad35a678b27cc281d7203b7bf3e5.png" alt="Image from Gyazo" /></a>
<h3>「sample2.pdf」を画像ファイルに変換してからテキストを抽出する</h3>
<pre><code>from PIL import Image
import sys
import pyocr
import pyocr.builders
import pdf2image

tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("No OCR tool found")
    sys.exit(1)

# The tools are returned in the recommended order of usage
tool = tools[0]
print("Will use tool '%s'" % (tool.get_name()))
# Ex: Will use tool 'libtesseract'


# pdfから画像オブジェクトに
images = pdf2image.convert_from_path("sample2.pdf", dpi=200, fmt='jpg')
lang = 'eng'
#lang = 'jpn'
# 画像オブジェクトからテキストに
for image in images:
    txt = tool.image_to_string(
        image,
        lang=lang,
        builder=pyocr.builders.TextBuilder()
    )
    print(txt)
</code></pre>
Sample2.pdfを使用してみます。

<a href="https://gyazo.com/248502418bfe563da40886936d04bbca"><img src="https://i.gyazo.com/248502418bfe563da40886936d04bbca.png" alt="Image from Gyazo" /></a>
<a href="https://gyazo.com/c8328f189eb22781bc17e16da4f73206"><img src="https://i.gyazo.com/c8328f189eb22781bc17e16da4f73206.png" alt="Image from Gyazo" /></a>
<a href="https://gyazo.com/2397eb15785734f8fa0bff9e0ba031fa"><img src="https://i.gyazo.com/2397eb15785734f8fa0bff9e0ba031fa.png" alt="Image from Gyazo" /></a>

言語が「eng」なので日本語部分は文字化けしていますが、コードの部分はある程度は正しく読み込まれています。
<h3><code>lang = 'jpn'</code>に変えて実行してみる</h3>
<a href="https://gyazo.com/81e594113f9440e1171a5ced3dc6459b"><img src="https://i.gyazo.com/81e594113f9440e1171a5ced3dc6459b.png" alt="Image from Gyazo" /></a>
<a href="https://gyazo.com/fbc96c35c4499f7aa9697d3349b78a13"><img src="https://i.gyazo.com/fbc96c35c4499f7aa9697d3349b78a13.png" alt="Image from Gyazo" /></a>
<a href="https://gyazo.com/af684acafa94ac650749d752984184d8"><img src="https://i.gyazo.com/af684acafa94ac650749d752984184d8.png" alt="Image from Gyazo" /></a>

先ほどより正しく読み込まれている部分が増え、読みやすくなりました。
<h3>ディレクトリとコード</h3>
今回のディレクトリ構成とコードをまとめるとこのような感じになります。

<a href="https://gyazo.com/4e0a5ac18f8b1423b95d88c2ef560f7e"><img src="https://i.gyazo.com/4e0a5ac18f8b1423b95d88c2ef560f7e.png" alt="Image from Gyazo" /></a>
<h2>【さいごに】</h2>
PDFファイルからテキストを抽出する方法を２つ試してみました。
特に、一度出力した資料をスキャンでPDFファイルにした場合は、スキャン精度によってテキスト抽出の精度も変わると思うので色々試してみる必要がありそうです。

興味ある方は、是非試して見てください。