手元の画像pdfファイルをOCR処理したいことがありました。
手軽にOCR処理する方法がないかを調べたところ、Google DriveにOCR機能があることを知りました。
GoogleDriveのOCR機能を使って、大量の画像ファイルをテキストに変換する
そこで、Google DriveのOCRを試してみることにしました。
なお、上の記事ではgdirveというCLIツールを使っていました。
prasmussen/gdrive: Google Drive CLI Client
PythonでGoogle Drive APIを使ってみたかったので探してみたところ、 PyDrive
がありました。
gsuitedevs/PyDrive: Google Drive API Python wrapper library
ただ、今回はファイルをアップロードするだけで複雑なことはしないため、Google APIのPythonライブラリ google-api-python-client
だけでGoogle Drive APIを使ってみます。
google/google-api-python-client
目次
環境
なお、画像としてpdf化されたファイル例として、今回は情報処理試験の過去問を使ってみます。
IPA 独立行政法人 情報処理推進機構:過去問題
今回は、基本情報処理試験の午前問題である 2017h29a_fe_am_qs.pdf
を使います。
最終的なディレクトリ構造は以下となります。
$ tree . ├── 2017h29a_fe_am_qs.pdf ├── __init__.py ├── client_id.json └── google_drive_ocr_uploader.py
Google Drive APIを使うための事前準備
Python Quickstartを参考に、事前準備を行います。
Python Quickstart | Drive REST API | Google Developers
プロジェクトの作成まわりは、以前のGmail APIの時と同様で良さそうです。
Python3 + google-api-python-clientで、Gmail APIを使ってメールを送信する - メモ的な思考的な
認証情報が含まれる client_id.json
ファイルは、実行用スクリプトと同じディレクトリに入れます。
調査事項
認証まわり
公式ドキュメントの get_credentials()関数まわりを使用します。
Step 3: Set up the sample - Python Quickstart | Drive REST API | Google Developers
なお、Python2.6関係のソースコードは削除しました。
Scopeはどうしようかと思いましたが、公式ドキュメントに
Per-file access to files created or opened by the app. File authorization is granted on a per-user basis and is revoked when the user deauthorizes the app.
https://developers.google.com/drive/v3/web/about-auth#OAuth2Authorizing
とあったため、 https://www.googleapis.com/auth/drive.file
を使うことにしました。
アップロードする時のMIMEタイプについて
どのようなMIMEタイプにすればよいか見たところ、
The extracted text will appear in the Google Docs document alongside the embedded image.
とありました。
ドキュメントにある表より、pdfの場合はGoogle DocsにするMIMEタイプを指定すれば良さそうでした。
Google DocsのMIMEタイプは application/vnd.google-apps.document
でした。
Supported MIME Types | Drive REST API | Google Developers
ocrLanguageの設定先について
OCRをどの言語で実行するかについては、 ocrLanguage
に設定すれば良さそうでした。
Files: create | Drive REST API | Google Developers
ライブラリのドキュメントを読むと、create()メソッドの引数に ocrLanguage
がありました。
https://developers.google.com/resources/api-libraries/documentation/drive/v3/python/latest/drive_v3.files.html
OCRの言語コードは ISO 639-1 codeで指定すればよいので、日本語の場合は ja
とします。
bodyパラメータで指定するファイル名について
アップロードするファイル名を指定します。
Google Docsにするからといって拡張子を外すと、以下のようにHTTP 400エラーが発生しますので、拡張子をつけたままにします。
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/upload/drive/v3/files?ocrLanguage=ja&alt=json&uploadType=resumable returned "Bad Request">
実装
import argparse import os import pathlib import httplib2 from apiclient import discovery from googleapiclient.http import MediaFileUpload from oauth2client import client from oauth2client import tools from oauth2client.file import Storage UPLOAD_FILE_NAME = '2017h29a_fe_am_qs.pdf' MIME_TYPE = 'application/vnd.google-apps.document' SCOPES = 'https://www.googleapis.com/auth/drive.file' CLIENT_SECRET_FILE = 'client_id.json' APPLICATION_NAME = 'ipa-google-drive-api-client' flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() def get_credentials(): """Gets valid user credentials from storage. If nothing has been stored, or if the stored credentials are invalid, the OAuth2 flow is completed to obtain the new credentials. Returns: Credentials, the obtained credential. """ home_dir = os.path.expanduser('~') credential_dir = os.path.join(home_dir, '.credentials') if not os.path.exists(credential_dir): os.makedirs(credential_dir) credential_path = os.path.join(credential_dir, 'drive-python-quickstart.json') store = Storage(credential_path) credentials = store.get() if not credentials or credentials.invalid: flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) flow.user_agent = APPLICATION_NAME credentials = tools.run_flow(flow, store, flags) print('Storing credentials to ' + credential_path) return credentials def upload_with_ocr(): credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('drive', 'v3', http=http) local_file_path = pathlib.Path(__file__).resolve().parent.joinpath(UPLOAD_FILE_NAME) media_body = MediaFileUpload(local_file_path, mimetype=MIME_TYPE, resumable=True) body = { 'name': local_file_path.name, 'mimeType': MIME_TYPE, } service.files().create( body=body, media_body=media_body, ocrLanguage='ja', ).execute() if __name__ == '__main__': upload_with_ocr()
実行結果
$ python google_drive_ocr_uploader.py
と実行後、自分のGoogleドライブの直下のディレクトリを見ると 2017h29a_fe_am_qs.pdf
ファイルが存在します。
複数ページのpdfでも、全ページOCR処理がなされていました。
ソースコード
GitHubに上げました。 google_drive_api
ディレクトリの中にあるものが今回のファイルです。
thinkAmi-sandbox/google-api-python-client-sample
*1:掲載してよいのか分からないため、結果は省略します