Zenn Tech Blog
😽

Notion APIとPythonを使ってページを作成する ~Slackへの通知を添えて~

2022/08/04に公開

チームで仕事やプロジェクトを行っていると定例MTGを実施することがあると思います。

その際に議事録のテンプレを作成したり、チームメンバーへ事前に議題の記載を展開するのをたまに忘れてしまうことってありませんか?
私はよくあります。人間がうっかり忘れてしまうような定型的な業務は自動化がピッタリです。ということで、今回はPythonとNotion APIを使って議事録の作成を自動化してみました。
ソースコードはページ後半で公開しているので、 内容とか別に良いからソース見たい!!って方は後半部分をご参照ください。

Notion APIの取得(事前準備)


NotionのAPIを利用するためには、以下のページから申請を行います。
APIの申請ページ

Create new Integrationをクリックすると、APIを利用することが可能です。

丁寧にGIF形式で申請するための方法が記載されているため、特に迷わずにAPIキーを取得することができると思います。
Internal Integration Token がAPIキーに該当します。流出するとセキュリティリスクがヤバいので大事に保管しましょう。

Notionでページを作成する際には、テーブル(または、データベース)にページを追加していく方法が一般的なようなので、今回はその方法で実装していきます。
作成したTokenをページに追加する必要があるため、忘れずに実施しましょう。

ページ作成を実装する


それでは、早速ページ作成の実装を行っていきたいと思います。
今回はテストとして、以下のデータベースにページを追加する前提で実装します。

テーブル構成

列名 Type 役割
Name Title ページ名を記載
Tags Multi-select ページのタグを記載
detail Text ページの説明
Created at Created time 作成日
Last edited at Last edited time 最終更新日
Created by Created by 作成者

議事録などでよく使うテーブルの構成ですね。
上記に記載のある列のTypeはAPIからリクエストする時に指定が必要になりますが、Notionのテーブル列名をクリックすると表示されます。

ページ作成の実装(Python)

公式ドキュメントを見てみるとJson形式でルール通りに情報を与えるとページの作成ができるようですが、NotionのAPIを利用してページを作成するには3つの要素が必要になります。

  1. url
  • 利用するAPIのURLを宣言します。
url = 'https://api.notion.com/v1/pages'
  1. headers
  • リクエストを送る際のヘッダー情報です。
    headers = {
        "Accept": "application/json",
        "Notion-Version": "2022-06-28",
        "Content-Type": "application/json",
        "Authorization": "Bearer " + api_key
    }
  1. payload
  • json形式で記載したページ情報です。
  • ページを作成する対象のデータベースのID情報は、 parentに記載
    • データベースのIDはURLから取得が可能です。対象ページを全画面で開いた際のURL構成の{database_id}の部分が該当します。
    • https://www.notion.so/{workspace_name}/{database_id}?v={view_id}
      公式ドキュメントはコチラ
  • ページの設定情報は properties に記載
  • ページの内容として記載したい内容は、 childrenに記載

上記のルールに沿って、記載を行うと👇のようになります。

   payload = {
       "parent": {
           "database_id": data_base_id
       },
       "properties": {
       "Name": {
           "title": [
           {
               "text": {
               "content": title_today
               }
           }
           ],
       },
       "Tags":{
           "multi_select":[
               {
                   "name":tag_name
                   }
           ]
       },
       "detail": {
           "rich_text": [
           {
               "text": {
               "content": detail_text
               }
           }
           ],
       },
       "date": {
           "date": {
               "start": created_iso_format
               }
           },
       }
       "children":[
           {
           "object": 'block',
           "type": 'heading_1',
           "heading_1":{
               "rich_text": [
           {
               "text": {
               "content": "今日のTopics!!!"
               }
           }
           ],
           }
       },
       ],}

上記のpropertieschildren の情報を実際のnotion画面と紐づけると以下のような構成です。

テーブルに列の追加や編集をしたい場合はpropertiesの変更を行い、ページ内部にblockを追加したい場合などはchildrenに追記を行えばOKです。

実装例

最終的なNotionでページ作成を行う実装は以下のように作成しました。ついでに、Slackへの通知も行いました。


import requests
import json
import datetime


today = datetime.date.today()
title = "チームMTG_議事録_"
title_today = title+ str(today)
created_iso_format = today.isoformat()
api_key = "取得したAPI Keyを記載"
data_base_id = 'データベースのIDを記載'
emoji = "🤠"
tag_name = "Weekly Sync"
detail_text = "チームの定例MTG"
slack_webhook_url ="Slackのwebhook url"


url = 'https://api.notion.com/v1/pages'

headers = {
    "Accept": "application/json",
    "Notion-Version": "2022-06-28",
    "Content-Type": "application/json",
    "Authorization": "Bearer " + api_key
}

payload = {
    "parent": {
        "database_id": data_base_id
    },
    "icon":{
        "emoji": emoji

    },
    "properties": {
    "Name": {
        "title": [
        {
            "text": {
            "content": title_today
            }
        }
        ],
    },
    "Tags":{
        "multi_select":[
            {
                "name":tag_name
                }
        ]
    },
    "detail": {
        "rich_text": [
        {
            "text": {
            "content": detail_text
            }
        }
        ],
    },
    "date": {
        "date": {
            "start": created_iso_format
            }
        },
    },
    "children":[
        {
        "object": 'block',
        "type": 'heading_1',
        "heading_1":{
            "rich_text": [
        {
            "text": {
            "content": "今日のTopics!!!"
            }
        }
        ],
        }
    },
     {
            "object": 'block',
            "type": 'heading_2',
            "heading_2":{
                "rich_text": [
            {
                "text": {
                "content": "アジェンダ"
                }
            }
            ],
            }
        },
        {
            "object": 'block',
            "type": 'heading_2',
            "heading_2":{
                "rich_text": [
            {
                "text": {
                "content": "Action Items"
                }
            }
            ],
            }
        },
        {
            "object": 'block',
            "type": 'to_do',
            "to_do":{
                "rich_text": [
            {
                "text": {
                "content": "ToDo 1"
                }
            }
            ],
            "checked": False,
            "color": "default",
            }
        }
    ],
}


response = requests.post(url, json=payload, headers=headers)

result_dict = response.json()
result = result_dict["object"]
page_url = result_dict["url"]


if result == "page":
    print("success")
    requests.post(slack_webhook_url, data=json.dumps({
    # メッセージ内容
    "text" : "今日の議事録が作成されたよ~!! みんなトピックを記載してね!! \n " + page_url,
}))
elif result == "error":
    requests.post(slack_webhook_url, data=json.dumps({
    # メッセージ内容
    "text" : "なんかエラーが発生しているみたい!まじごめん!! 手動で議事録作って!! \n " + page_url,
}))
else:
    requests.post(slack_webhook_url, data=json.dumps({
    # メッセージ内容
    "text" : "例外起きて草。なんも分からん。とりあえず手動で議事録作って。ごめんね。。 \n " + page_url,
    }))

上記を実行するとページの作成は問題なく実施できると思います。 議事録っぽくするために、ToDoの記載をするためのチェックボックスなども記載しました、Let’s あくしょん。

もし、エラーが発生する場合は、列名とpropertiesの指定が異なることやAPI Key/Database IDの設定が不正である可能性を疑ってみてください。
Slackへの通知は、作成結果ごとに出し分けを行っています。

まとめ

初めてNotionのAPIを利用しましたが、忘れがちな作業をサクッと自動化できたので非常に便利でした。この実装を特定頻度(週に一回とか)で実行すれば、イイ感じに定例MTGのメモの作成とかは自動化できますね。私はCloud FunctionとCloud Schedulerで自動化を行いました。
今後は、絵文字が毎回同じになるのも退屈なので、ランダムに変更することなどもやってみたいなと思います。
Notionの他のBlockの記載方法などについては、公式ドキュメントが参考になるためご参照ください。

参考

https://developers.notion.com/

Zenn Tech Blog
Zenn Tech Blog

Discussion