5
9

Pythonを用いて、スキャンしたPDFからテキスト抽出してみよう!

Last updated at Posted at 2023-12-11

はじめに

 みなさんこんにちは、Hagianです。現在大学院修士2年に在学しています。本記事では、最近文献を読むにあたって直面した問題と、解決方法について簡単に紹介したいと思います。

背景・直面した問題

 学術論文をはじめとする、研究に関連する文献は近年、電子媒体で発行されるのが一般的になってきています。また、過去に発行された文献についても、電子化して公開する流れはかなり活発になってきています。これらの文献は、PDFとして公開されるのが一般的です。

 最近発行された文献の場合、PDFにフォントが埋め込まれている場合が多く、一字一句変えずに利用する場面(論文を引用するとき/翻訳したいとき/参考文献リストを作るとき etc..)で困ることはあまりありません。しかし、過去に紙媒体で発行された文献が電子化を経て公開された場合であったり、自分で文献をスキャンして保存した場合などは、ほとんどPDFにフォントが埋め込まれておらず、そのままではドラッグ&ドロップでコピーすることはほぼ不可能です。

 そこで今回、Pythonと文字認識ライブラリを用いて、PDFからテキストを抽出したのでその方法を以下に記します。

使ったもの

  • pdf2image

PDFを画像ファイルに変換するためのライブラリです。

  • PyOCR

PythonのOCR(光学文字認識)ツールで、さまざまなOCRエンジンを利用できます。

  • Tesseract

Googleが開発したOCRエンジンで、以下リポジトリから無料でダウンロードすることができます。

開発環境

  • macOS Ventura 13.6
  • VSCode 1.84.2
  • Python 3.11.6

前準備

 開発にあたり、まず必要なもののインストールを行いました。TesseractはGithubからダウンロード可能ですが、Homebrewからもインストールできます。

$ brew install poppler tesseract

ここでインストールしているpopplerは、PDF閲覧用のライブラリで、pdf2imageが必要としています。Macの場合はHomebrewからインストールできます。

$ pip install pdf2image pyocr

pdf2image、pyocrともにpipから簡単にインストールできます。

Tesseractについて

 Tesseractには3種類のエンジンがあり、それぞれ長所が異なります。

  • 通常版
  • fast版(実行速度重視)
  • best版(精度重視、実行速度はやや遅い)

上記のように、Homebrewからインストールすると、実行速度を重視したfast版が導入されるようです。このあたりは以下Qiita記事が詳しいです。

今回は元のPDFからできるだけ正確にテキストを抽出するため、best版を用いることにしました。上記Qiita記事を参考に、Githubからダウンロードし、データを入れ替えました。

また、Tesseractのエンジンは言語別になっているため、日本語など英語以外を必要とする場合には、都度ダウンロードが必要な点に注意してください。

実現したこと

 今回は、PDFとして保存した英語の文献を読み込み、テキストだけ抽出してファイルに書き出す、という操作を実装しました。

pdf_ocr.py
from pathlib import Path
from pdf2image import convert_from_path
import pyocr
import pyocr.builders
import sys

# 使用可能なOCRツールを探す
tools = pyocr.get_available_tools()
tool = tools[0]
if len(tools) == 0:
    print("OCR tool is not found.")
    sys.exit(1)
lan = "eng"

# 抽出したいファイル名を指定
f_name = "hogehoge"

# パスを設定
pdf_path = Path(f"./{f_name}.pdf")
txt_path = Path(f"./{f_name}.txt")

# PDFから画像ファイルに変換
pages = convert_from_path(str(pdf_path), 300)

txt = ""
for i, page in enumerate(pages):
    txt = txt + tool.image_to_string(page, lang=lan, builder=pyocr.builders.TextBuilder(tesseract_layout=6))

# テキストファイルに書き出し
with open(txt_path, mode="w") as f:
    f.write(txt)
print("Process completed!")

使ってみた感想

 実際にこのコードを用いて、筆者がスキャンした論文(英文50ページ)のテキスト抽出に取り組んでみました。

すると5分程度で、精度およそ95%のテキスト抽出に成功しました。

テキストファイルとPDFを比較してみてみると、裏側の文字を認識している箇所がいくつかあり、人間の目よりも精度がいいのでは…?と思いました…。

参考にした記事

5
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9