Notion で Google Drive の OCR を簡単に使えるんですか!?
Notion から使える OCR 機能が欲しかったので、下記の記事を参考に GAS のライブラリーを作ってみました。
この記事ではライブラリーの設定方法などを記載していきます。
どんなライブラリー?
Google Drive 上に保存されている PDF と画像に OCR を実行し、結果のテキストを Notion へ送信するライブラリーです。
定期実行や変更通知に対応しているので、OCR の結果を自動的に Notion へ送信できます。
▼ 図 1-1 PDF を所定のフォルダーに保存すると
▼ 図 1-2 テキストとして Notion へ送信される
また、少し設定を頑張れば「スマートフォンのカメラで撮影した後、リアルタイムに近い感覚で OCR の実行」も可能です。
▼ 図 1-3 フォルダーに保存後、10 ~ 20 秒くらいでテキストが登録される(実際の画面にタイムコードは表示されません)
おおまかな設定の流れ
設定する項目がサービス別に分散していたりするので、最初に少し整理します。
おおまかなには、以下のような設定することで Notion から OCR が利用できるようになります。
-
Notion 側では API キーやテキストを受け取るデータベースを用意
-
Google Drive 側ではスキャンしたファイルを保存するフォルダーを作成
-
Google Apps Script でライブラリーを利用するためのプロジェクトを作成
- プロジェクトの定期実行などのカスタマイズを適宜行う
Notion 側の準備
Notion API キー(インテグレーション)を作成
外部(Google App Script)から Notion を利用するための API キーが必要です。
「私のインテグレーション | Notion 開発者」からインテグレーションを作成し API キーをメモしておきます。
▼ 図 3-1 上記リンクを開いたら「+ 新しいインテグレーション」をクリック
▼ 図 3-2 基本情報の「名前」へ「OCR」などを入力
▼ 図 3-3 画面を下にスクロールし「ユーザー機能」 は「ユーザー情報なし」へ変更、その後「送信」をクリック
▼ 図 3-4 インテグレーションが作成されたらトークン欄の「表示」をクリックし内容をメモ(コピー)
Notion データベースの用意
必須のプロパティはないのでデータベースであれば既存のもの、新規作成のものどちらでも利用できます。
既存のデータベースを利用する場合はブラウザーで開き id をメモします。
▼ 図 3-5 アドレスバーの赤く塗りつぶした部分をメモ
以下は新規作成する場合の操作例です。
▼ 図 3-6 任意のページで「/data」と入力後、「データベース: フルページ」を選択
▼ 図 3-7 データベース名を「OCR」などへ変更
▼ 図 3-8 ビューのレイアウトを「ギャラリー」など扱いやすい設定へ変更
▼ 図 3-9 アドレスバーの赤く塗りつぶした部分をメモ
なお、この方法でデータベースを作成した場合、デフォルトでブランクのレコードが 3 件追加されています。とくに必要はないので削除してください。
Notion データベースを APIキー(インテグレーション)と共有する
API キーでデータベースを操作できるように共有する必要があります。
用意したデータベースを開き以下のように操作します。
▼ 図 3-10 データベース画面の右上にある「共有」をクリック
▼ 図 3-11 「ユーザー、メール…」などが表示されているフィールドをクリック
▼ 図 3-12 作成したインテグレーションを選択
▼ 図 3-13 「招待」ボタンをクリック
▼ 図 3-14 インテグレーションが追加されたら完了です
Google Drive 側の準備
Google Drive 側ではスキャンされた PDF などを保存するためのフォルダーが必要です。フォルダーを 1 つ作成し id をメモしておきます。
▼ 図 4-1 フォルダーを表示しアドレスバーの赤く塗りつぶした部分をメモ
ライブラリーの利用(基本編)
ライブラリーの利用法はいくつかありますが、ここでは簡単なプロジェクトを作成してみます。
プロジェクトを作成
Google Drive のウェブ UI で Google Apps Script プロジェクト(ファイル)を作成します。
おおまかな手順としては「プロジェクトを作成し名前の設定」「ライブラリーの追加」「Drive API サービスの有効化」「スクリプトコードの編集」となります。
なお、今回は手順の簡略化のために API キーなどをコードにべた書きしていますが、できれば他の方法(プロパティサービスの利用など)を検討してください。
▼ 図 5-1 ブラウザーの Google Drive で右クリックし「Google Apps Script」を選択
▼ 図 5-2 「無題のプロジェクト」のところをクリックしプロジェクト名を変更
プロジェクト名を変更したら、OCR のライブラリー(1phsqy39NYEBOCpGx062N9kezLOdyzRKSEgDBYt6f-zaqVdAOdn9NaWWH
)を追加します。
▼ 図 5-3 「ライブラリー」横の「+」をクリック
▼ 図 5-4 スクリプト ID 1phsqy39NYEBOCpGx062N9kezLOdyzRKSEgDBYt6f-zaqVdAOdn9NaWWH
を入力し「検索」をクリック
▼ 図 5-5 バージョンはその時点で最新のものを選択、ID を「GocrToNotion」へ変更
続いて Drive サービスを有効化します。
▼ 図 5-6 「サービス」横の「+」をクリック
▼ 図 5-7 一覧から「Drive API」 を選択し「追加」をクリック
最後にエディター上の myFunction
を以下のように変更します。このとき各項目をメモしておいた値へ置き換えます。
-
'notion_api_key'
にはインテグレーションの API キーを記述 -
'database_id'
には用意したデータベースの id を記述 -
'folder_id'
には作成したフォルダーの id を記述
function myFunction() {
const apiKey = 'notion_api_key'
const database_id = 'database_id'
const folder_id = 'folder_id'
const opts = {
database_id,
ocrOpts: [
{
scanFolderId: folder_id,
ocrFolderId: folder_id,
ocrLanguage: 'ja',
tags: [],
removeOcrFile: true
}
]
}
GocrToNotion.ocr(apiKey, opts)
}
OCR を実行してみる
作成したフォルダーに PDF か画像ファイルを保存します。
スマートフォンのカメラを使う場合は以下のようにします。
▼ 図 5-8 Google Drive のアプリでフォルダーを表示し「+」、「スキャン」をタップ
▼ 図 5-9 スキャンして PDF をフォルダーへ保存します
フォルダーにファイルが保存されたらスクリプトエディターから myFunction
を実行します。
▼ 図 5-10 「実行」ボタンをクリック
初回実行時には、以下のような画面が表示されるので、今回利用するライブラリーを怪しいと思わなければ画面を進めてください。
▼ 図 5-11 「権限を確認」ボタンをクリック
▼ 図 5-12 赤く塗りつぶした部分が自身のメールアドレスであることを確認し、左下の「詳細」をクリック
▼ 図 5-13 画面が展開されるので左下の「(安全ではないページ)に移動」をクリック
▼ 図 5-14 利用される権限が表示されるので確認
▼ 図 5-15 画面をスクロールさせ「許可」ボタンをクリック
問題がなければ、少し待った後に OCR の結果のテキストが Notion のデータベースに追加されます。また、このとき元の PDF ファイルの説明にもテキストがセットされます。
▼ 図 5-16 Notion のデータベースにテキストが追加される
▼ 図 5-17 Google Drive のファイルに説明テキストが追加される
ライブラリーの利用(応用編)
定期的に実行する
毎回スクリプトエディターから実行するのは大変なので、以下のように設定しておくと定期的に実行できます。
▼ 図 6-1 スクリプトエディターの「時計」アイコンをクリック
▼ 図 6-2 画面が切り替わったら、右下の「トリガーを追加」ボタンをクリック
▼ 図 6-3 デフォルトで「1 時間おき」に実行される設定画面が表示される
▼ 図 6-4 画面をスクロールさせ「保存」ボタンをクリック
なお、フォルダーに複数のファイルがあった場合、作成日時の新しい順に 100 ファイルを対象とします。また、ファイルの説明が空欄でない場合は OCR 処理をスキップします。
よって、以下のようなファイルは対象にならないので注意してください。
- 作成日時が古いファイルを別フォルダーからコピーした場合
- ファイルの説明を追加している場合
フォルダー別に設定を切り替える
以下のように ocrOpts
の配列で異なるフォルダーを指定すると、フォルダー毎に設定の切り替えができます。
const opts = {
database_id,
ocrOpts: [
{
scanFolderId: folder_id1,
ocrFolderId: folder_id1,
ocrLanguage: 'ja',
tags: ['メモ'],
removeOcrFile: true
}, {
scanFolderId: folder_id2,
ocrFolderId: folder_id2,
ocrLanguage: 'ja',
tags: ['レシート'],
removeOcrFile: true
}
]
}
PDF へのリンクを追加
Notion のデータベースに link
プロパティを追加すると、Google Drive 上のファイルへリンクされます。
▼ 図 6-5 link にURL が追加され、クリックすると Google Drive のファイルを開く
テキストの先頭部分をプロパティにセットする
Notion のデータベースに excerpt
プロパティを追加すると、テキスト先頭の 1900 バイトがセットされます。
▼ 図 6-6 excerpt にもテキストが追加される
ライブラリーの利用(ほぼリアルタイム編)
Google Drive の変更通知(プッシュ通知)を利用すると、ファイル追加時にほぼリアルタイムで OCR を実行できます。原理的な部分は長くなるので[1]、ここでは設定についてのみを記載します。
最初に「ライブラリーの利用(基本編)」で作成したプロジェクトのコードを以下のように変更します。
ocr
関数の各項目は「ライブラリーの利用(基本編)」のときと同じです。settings_
関数の deploy_url
は後から変更するので、ここではこのままにしておきます。
function ocr_(list) {
const apiKey = 'notion_api_key'
const database_id = 'database_id'
const folder_id = 'folder_id'
const opts = {
database_id,
ocrOpts: [
{
scanFolderId: folder_id,
ocrFolderId: folder_id,
ocrLanguage: 'ja',
tags: [],
removeOcrFile: true
}
]
}
GocrToNotion.send(apiKey, opts, list)
}
function settings_(properties) {
const expiration = 61
const address = 'deploy_url'
return {
resource: {
id: Utilities.getUuid(),
type: 'web_hook',
token: '',
expiration: `${new Date(
Date.now() + 60 * expiration * 1000
).getTime()}`,
address
}
}
}
function doGet(e) { }
function doPost(e) {
if (e.postData && e.postData.contents) {
const lock = LockService.getScriptLock()
if (lock.tryLock(10 * 1000)) {
try {
const props = PropertiesService.getScriptProperties()
const pageToken = props.getProperty('page_token')
const res = Drive.Changes?.list({ pageToken })
ocr_(res)
props.setProperty('page_token', res?.newStartPageToken || '')
} catch (e) {
console.error(e)
} finally {
lock.releaseLock()
}
}
}
}
function reset() {
const props = PropertiesService.getScriptProperties()
const properties = props.getProperties()
const settings = settings_(properties)
const resToken = Drive.Changes?.getStartPageToken()
const pageToken = JSON.parse(resToken).startPageToken
props.setProperty('page_token', pageToken)
const res = Drive.Changes?.watch(settings.resource)
console.log(JSON.stringify(res, null, ' '))
try {
stop(properties)
} catch (e) {
console.error(e)
}
properties.channle_id = settings.resource.id
properties.resource_id = res?.resourceId || ''
props.setProperties(properties)
}
function stop(inProperties) {
const props = PropertiesService.getScriptProperties()
const properties = inProperties || props.getProperties()
const { channle_id, resource_id } = properties
if (channle_id && resource_id) {
const res = Drive.Channels?.stop({
id: channle_id,
resourceId: resource_id
})
console.log(JSON.stringify(res, null, ' '))
}
}
コードを変更したら deploy_url
の値を確定させます。
▼ 図 7-1 スクリプトエディター右上の「デプロイ」「新しいデプロイ」をクリック
▼ 図 7-2 画面が表示されたら歯車アイコンをクリック
▼ 図 7-3 「ウェブアプリ」をクリック
▼ 図 7-4 「アクセスできるユーザー」を「全員」へ変更し「デプロイ」ボタンをクリック
▼ 図 7-5 デプロイの「URL」をメモ(コピー)し「完了」ボタンをクリック
▼ 図 7-6 コピーした URL を settings_
関数の deploy_url
へセット
これで更新通知にあわせて OCR を実行する設定は完了しました。
動作確認のためにスクリプトエディターから reset
関数を実行します。
▼ 図 7-7 スクリプトエディターのツールバーで reset
関数を選択し「実行」をクリック
▼ 図 7-8 Google Drive 上のファイル変更にあわせてログが追加される
この状態で OCR 用のフォルダーに PDF ファイルを追加すると OCR が実行されます[2]。
ただし、通知設定の有効期限を 61 分としているので、以下のように時間主導のトリガーを設定し 1 時間毎にリセットさせます。
▼ 図 7-9 実行する関数を reset
へ変更してトリガーを追加
これで OCR 用のフォルダーへ PDF ファイルを追加したら OCR が実行される状態が永続化されます。
状態を停止させるときはスクリプトエディターから stop
関数を実行させてください。
おわりに
Notion から Google Drive の OCR を利用できるライブラリーを作ってみました。
作ってからまだ日が浅いのでそれほど使い込んでいませんが、掲示物などをメモするときの負担は減らせたと実感しています。
また、今回の記事では割愛していますが、Notion へ送信する内容を操作できるようにもしてあるので[3]、翻訳などのサービスを組み合わせるのも便利そうかなと考えています。
少し張り切りすぎて設定方法を長々と書いてしまいましたが、定期的な OCR の実行は比較的手軽にできるので、よければ試してみたください。
-
GAS と変更通知については「Google Drive の変更通知を Google Apps Script で受け取る」で記事にしています。 ↩︎
-
今回の設定ではログの詳細は確認できません。プロジェクトを GCP プロジェクトへ変更することで確認できます(Google Cloud Platform Projects | Apps Script | Google Developers)。 ↩︎
-
「Notion を通知機能付き RSS フィードリーダーぽくする GAS ライブラリーを作ってみた」の Transformer と同じようなことができます。 ↩︎
Discussion
この度は参考にさせていただきました。ありがとうございます。
1点質問があってコメントさせていただきました。
スマホで撮影した名刺画像がNotionページのカバー画像に自動で設定されておりますが、こちらの画像をページのファイル&メディアプロパティにも自動で保存されるようにすることは可能ですか?
ただ、この場合はリンクではなく、実際のデータが自動でアップされるようにしたいのです。
もし可能であれば手順をご教示いただけますと幸いです。
何卒ご確認の程よろしくお願い致します。
できれば対応したいところではあるのですが、ファイル&メディアプロパティへのアップロードは Notion API でサポートされていない機能であるため現状では難しいです。
なお、外部リンクとしてなら設定する方法はあるので(何かの参考になるかもしれませんので)そちらを記載させていただきます。ただし、実用的に使うにはいくつか難点があります(おそらくその辺の問題もあっての今回のご質問かとは思いますが…)。
クリックすると設定例が表示されます
以下、名前が「サムネイル」のファイル&メディアプロパティを追加されている前提で、関数を追加した設定例です。
この場合、「サムネイル」プロパティに外部リンクは設定されますが、以下のようにサムネイル表示にはならないので画像を確認するにはリンクを開く(クリックする)必要があります。

また、 Google ドライブのサムネイル画像は有効期限があるため、ある程度の時間が経過するとクリックしてもエラーとなります。よって、クリック操作が必要になるならば、単純に既存の「link」プロパティをクリックする方が関数追加の手間がなくて良いかと思います。
あとは、Notion 側のページでサムネイルを表示させることが目的であるならば、手動操作になりますが Notion の Google Drive への接続機能を使って本文中にプレビューを作成するという方法も考えられます。
(すでにご存知でしてたらすみません)
クリックすると具体的な操作手順が表示されます
具体的手順としては以下のようになります。
「link」 プロパティの内容をコピーする。

本文中に「プレビュー」として貼り付け、「Google Drive に接続して更新」をクリックし接続する(2 回目移行は接続操作は必要ありません)

接続されるとプレビューが表示される。

ただし、この方法も問題点がいくつかあるため、実用的かというとやはり少し難点があるかと思います。
他にもいくつか代替案を試してはみたのですが、やはり Notion API 側でファイルアップロード機能がサポートされないと現状では難しいと言うのが正直なところです。
あまりお役に立てない返答となってしまいましたが、よろしくお願い致します。
詳細にご連絡いただき誠にありがとうございます。
今後も楽しみに購読させていただきます🙇
すみません、バッジを追加購入しようと思ったのですが一度きりでしたので下記ページで購入させていただきました。引き続きで質問させてください🙇
GitHubに以下のプロパティ設定について書かれていたのですが、Notionに値が入ってきません。
これらを任意で設定したい場合、どこを触れば良いのでしょうか?
あと、カバー画像だけではなく、アイコンも自動でセットさせたいのですがそのようなことはできるのでしょうか??
プロパティ名 プロパティの種類 内容
entryUpdated 日付 データベースのエントリー更新日時
guid テキスト ファイルの id
mimeType セレクト ファイルの mimeType
type セレクト ファイルの種類
tags マルチセレクト OCR オプションで指定したタグ
タグ マルチセレクト OCR オプションで指定したタグ
excerpt テキスト OCR テキストの先頭 1900 バイト
description テキスト ファイルの説明
link URL ファイルへのリンク
modified 日付 ファイル更新日時
バッジありがとうございます、記事作成の励みになります。
プロパティについてですが、Notion 側のデータベースへ事前に手動でプロパティを作成しておく必要があります。
以下は、

mimeType
プロパティを手動で作成しておき OCR を実行した例です。ただし注意点があります。プロパティの種類が正しくないと値はセットされません。たとえば、

type
は「セレクト」である必要がありますが、「テキスト」が設定されていると未入力のままとなります。また、プロパティを追加しても、すでに Notion 側に作成されたページのプロパティは未入力のままです。
以下の例では1ページ目作成後に

link
プロパティを作成しています。よって、link
プロパティに値がセットされるのは2ページ目からとなっています。プロパティを事前に正しく作成されていても値がセットされていないときは、「作成されたプロパティ名とプロパティにセットされることが期待される値」「エラーメッセージ」など、原因を特定できそうな情報を教えていただけますか。
オプションの
paramTransfomers
にジェネレーター関数を指定することで絵文字か外部の画像ファイルを指定できます(画像ファイルをアップロードすることはできません)。// アイコンを指定
コメントの下にあるemoji:
かexternal:
のどちらかを利用することでアイコンを変更できます。以下は

emoji: '😀'
を指定したときの例です。なお、外部の画像ファイルの指定は画像ファイルを誰でも参照できる状態にする必要があるので、絵文字を指定するのが簡単で安全かと思います。
ありがとうございます!!!
絵文字のほうを早速試したのですが、うまくいきませんでした。
以下のコードにマージしたのですが・・・
GocrToNotion.send(apiKey, opts, list)が問題ですかね?
あと、paramTransfomersのスペルを指摘されたのですが、いかがでしょうか?
const opts = {
database_id,
ocrOpts: [
{
scanFolderId: folder_id,
ocrFolderId: folder_id,
ocrLanguage: 'ja',
tags: ["名刺"],
description:[""],
removeOcrFile: true
}
// フォルダ分けする場合は下記を生かしてid2を作る
// , {
// scanFolderId: folder_id2,
// ocrFolderId: folder_id2,
// ocrLanguage: 'ja',
// tags: ['レシート'],
// removeOcrFile: true
// }
]
}
GocrToNotion.send(apiKey, opts, list)
それと、プロパティの件ですが、以下の画像の3つのプロパティ(excerpt以外)が入ってこないんですよね…

GocrToNotion.send() でのコード変更
再度デプロイが必要です
GocrToNotion.send(apiKey, opts, list)
ということは、「ライブラリーの利用(ほぼリアルタイム編)」の手順を利用されているかと思います。記事の方で説明が抜けてしまっているのですが、コードを修正した後に再度デプロイと新しい
deploy_url
の設定が必要となります。(再設定しないと修正前のデプロイ時点でのコードが実行されます)
具体的には記事中の以下の範囲の操作となります。
なお、2回目以降であれば
は既に選択状態になっていてスキップできるはずです。
新しいデプロイでのコードで動作しているかは、ログの方にバージョン情報が表示されるのでそちらで確認できるかと思います。

paramTransfomersのスペルについて
これは、ライブラリ作成時のタイプミスで
paramTransfomers
と記述する必要があります。なお、スペルミス指摘が気になる場合は、修正したライブラリを作ったので(バージョン7以降)へ切り替えれば、
paramTransfomers
とparamTransforme
のどちらでも動作するようになっています。ライブラリのバージョン切り替えはスクリプトエディターでライブラリ名をクリックすることで行えます。(切り替えを行った場合も再デプロイが必要です)


実際に使用したコード(抜粋)について
こちでは以下のようなコードで動作を確認しています。
以下は実行された結果です。

デプロイしなおしても動作しない場合は、上記に該当する部分のコードを差し支えない範囲で見せていただけますか。
プロパティへのセット
tags の変更も再デプロイが必要です
上記のタグについての記述ですが、あとから追加された場合はこちらも再度デプロイが必要となります。
descriptiom プロパティへのセットは機能していませんでした
descriptiom
プロパティについては、Google ドライブ側のファイルの説明をセットするつもりでしたが、処理的に「OCR 対象のファイルは説明が空欄のものとする」となっているので意味がない(常に空白となる)ものとなっていました。こちらはあとで処理を削ってリポジトリの README からも削除しておきます。新規に Google Apps Script プロジェクト(ファイル)を作成しなおす場合
再デプロイとライブラリの更新などが煩雑になり状況が混乱した場合、Google Apps Script プロジェクト(ファイル)を作成しなおす方がスッキリとわかりやすくなるかと思います。
その場合、古いプロジェクトをそのままにしておくと2重に OCR が実行されるなどの不具合が出るかもしれないので、以下のように古いプロジェクトを削除してください。
stop
関数を実行新しいプロジェクトを作成するときは、「ライブラリーの利用(基本編)」から始めてください。
このとき、応用編へ進む前にタグや絵文字アイコン用のコードと設定を試しておくと問題を切り分けやすくなるかと思います。