LoginSignup
26
18

【保存版】Python Notion 操作 (notion-sdk-py編)

Last updated at Posted at 2023-07-18

こんばんは、本日はPythonでNotionを操作する方法について解説します。
私も普段からNotionはかなり利用しており、蓄積した大量のデータを再利用したいと思い少し触ってました。

Notion公式ではTypeScript版のSDKは公開されていますが、Python版は公式からありませんでしたので、有志の方が公式TypeScriptを元にPython版SDKを作成してくれています。

以下です👋
https://github.com/ramnes/notion-sdk-py

辞書的に使えるに記事を作成しますので、是非いいねや保存お願いします!!
基本的に以下を組み合わせることで何でも作れると思います!

前提条件

インテグレーションの作成

NotionAPIを利用するために、以下のサイトにアクセスしてインテグレーション新規作成をします。
https://www.notion.so/my-integrations

基本は社内でNotionデータを二次利用することになるのでインターナルとしておくのが無難です。
image.png

以下のシークレット情報はNotionAPIを操作するのに必要ですので、大切に管理してください。
image.png

インテグレーションの接続

APIで操作したいページにはコネクタを追加する必要があります。
下図のように作成したインテグレーションを操作したいページにコネクトしてください。

image.png

ライブラリのインストール

pip install notion-client

操作対象

今回はサンプルとして以下のデータベースをPythonで操作することを想定します。

image.png

データベースID

本データベースのリンクをコピーからURLを取得して、その中からデータベースIDを抽出します。
?v=の直前の32桁のIDとなります。

image.png

ページID

各レコードごとのページIDの取得も基本はデータベースIDの取得と同様です。
対象のページを開いて、リンクを取得して32桁のIDを取得します。

基本概念

APIで操作するときの基本となる概念としては以下を理解しておいてください。
NotionではPropertiesとChildrenの2つで構成されています。

  • Properties : Title, カテゴリなどのページの付加情報
  • Children : ページのメインコンテンツ

image.png

ソースコード

インスタンスの生成

Clientインスタンス作成時に引数として、インテグレーションのシークレット情報を利用します。
基本的にシークレット情報などはソースコードに埋め込まず、envファイル等から読み込むようにしてください。

import os
from notion_client import Client

token = os.environ.get("NOTION_TOKEN")
client = Client(auth=token) # token: インテグレーションのシークレット情報

ワークスペースのユーザー一覧を取得する

以下の処理ではゲストユーザーの情報は取得できないことに注意が必要です。

def get_all_notion_users():
    response = client.users.list()
    return response

データベースの全ての情報を取得する

def read_notion_database(database_id):
    response = client.databases.query(
        **{
            "database_id": database_id,
        }
    )

    print(response)
    return response

データベースの中からStatus列がDoneの情報のみを取得する

def read_notion_database(database_id):
    response = client.databases.query(
        **{
            "database_id": database_id,
            "filter": {
                "property": "Status",
                "status": {
                    "equals": "Done"
                }
            }
        }
    )

    print(response)
    return response

データベースに存在するレコードのページID一覧を取得する

def read_pages_from_database(database_id):
    response = client.databases.query(
        **{
            "database_id": database_id,
        }
    )

    results = response["results"]
    page_ids = []
    for result in results:
        # print(f'page_id={result["id"]}')
        page_ids.append(result["id"])

    print(f"read_pages_from_database completed. (len={len(page_ids)})")
    return page_ids

ページ内のコンテンツを全て取得する

ページのプロパティやコンテンツを全て取得するときに使用します。

def get_page_content(page_id):
    response = client.blocks.children.list(
        **{
            "block_id": page_id,
            "page_size": 50
        }
    )

    return response

指定したページのTitleプロパティを取得する

def get_page_title(page_id):
    response = client.pages.retrieve(
        **{
            "page_id": page_id,
            "properties": [
                "Title"
            ]
        }
    )

    return response["properties"]["Title"]["title"][0]["plain_text"]

指定したページのStatusプロパティの値を取得する

def get_page_status_property(page_id):
    response = client.pages.retrieve(
        **{
            "page_id": page_id,
            "properties": [
                "Status"
            ]
        }
    )

    return response["properties"]["Status"]["status"]["name"]

指定したページのEmailプロパティを取得する

def get_page_email_property(page_id):
    response = client.pages.retrieve(
        **{
            "page_id": page_id,
            "properties": [
                "Email"
            ]
        }
    )

    return response["properties"]["Email"]["email"]

データベースに新規レコードを追加する

少しコード長くなります。
各プロパティで日本語を使用している場合はエンコードした文字列を使用する必要があります。

以下のようなページが追加されます。
応用しやすいように様々な種類のプロパティやページコンテンツでも良く使う要素を入れています。
image.png

def add_row_to_notion_database(database_id):
    response = client.pages.create(
        **{
            "parent": { "database_id": database_id },
            "icon":{
                "emoji": 😂

            },
            # ページのプロパティを指定する
            "properties": {
                "Title": {
                    "title": [
                        {
                            "text": {
                                "content": "yyyyMMddHHmmss"
                            }
                        }
                    ]
                },
                "\u30ab\u30c6\u30b4\u30ea": { # カテゴリ
                    "multi_select": [
                        {
                            "name": "\u30ab\u30c6\u30b4\u30ea1", # カテゴリ1
                        },
                        {
                            "name": "\u30ab\u30c6\u30b4\u30ea2", # カテゴリ2
                        },
                        # 選択肢が存在しない場合は自動で新規作成される
                        {
                            "name": "\u30ab\u30c6\u30b4\u30ea3", # カテゴリ3
                            "color": "red"
                        },
                        # 自動作成時、カラーを設定しないときは自動で付与される
                        {
                            "name": "\u30ab\u30c6\u30b4\u30ea4", # カテゴリ
                        }
                    ]
                },
                "Status": {
                    "status": {
                        "name": "In progress", # Done, In progress, Not started
                    }
                },
                "\u30c1\u30a7\u30c3\u30af": { # チェック
                    "checkbox": True # False
                },
                "\u512a\u5148\u5ea6": { # 優先度
                    "select": {
                        # "id": "aa5f95d4-cb4c-42ef-a418-46257b73cb62",
                        "name": "\u9ad8", # 高
                    }
                },
                "Email": {
                    "email": "test@example.com"
                },
                "Note": {
                    "rich_text": [
                        {
                            "text": {
                                "content": f"test {get_current_time()}",
                            }
                        }
                    ]
                }
            },  # end properties
            # ページ内にコンテンツを追加する場合はchildrenを指定する
            "children" : [
                # toc block
                {
                    "object": "block",
                    "type": "table_of_contents",
                    "table_of_contents" : {}
                },
                # heading 1
                {
                    "object": "block",
                    "type": "heading_1",
                    "heading_1" : {
                        "rich_text": [
                            {
                                "text": {
                                    "content": "Heading 1"
                                }
                            }
                        ]
                    }
                },
                # heading 2
                {
                    "object": "block",
                    "type": "heading_2",
                    "heading_2" : {
                        "rich_text": [
                            {
                                "text": {
                                    "content": "Heading 2"
                                }
                            }
                        ]
                    }
                },
                # heading 3
                {
                    "object": "block",
                    "type": "heading_3",
                    "heading_3" : {
                        "rich_text": [
                            {
                                "text": {
                                    "content": "Heading 3"
                                }
                            }
                        ]
                    }
                },
                # link
                {
                "object": "block",
                "paragraph": {
                    "rich_text": [
                        {
                            "text": {
                                "content": "Here is ATD website.",
                                "link": {
                                    "url": "https://www.atd-net.com"
                                }
                            },
                            "href": "https://www.atd-net.com"
                        }
                    ],
                    "color": "blue"
                    }
                },
                # code block python
                {
                    "object": "block",
                    "type": "code",
                    "code": {
                        "caption": [],
                        "rich_text": [
                            {
                                "type": "text",
                                "text": {
                                    "content": "x = aaa\nprint(x)",
                                    "link": None
                                },
                            }
                        ],
                        "language": "python"
                    }
                },
            ]
        }
    )

    print("notion database create completed")
    print(response) # 追加した内容を表示する

ページの一部のプロパティを編集

今回はStatus列をDone, 優先度列をに変更します。

def update_page_properties(page_id):
    response = client.pages.update(
        **{
            "page_id": page_id,
            "properties": {
                "Status": {
                    "status": {
                        "name": "Done", # Done, In progress, Not started
                    }
                },
                "\u512a\u5148\u5ea6": { # 優先度
                    "select": {
                        "name": "\u9ad8", # 高
                    }
                }
            }
        }
    )

    print("notion database update response")
    print(response)

さいごに

以上、Pythonで操作するNotionでした!!
自由に組み合わせて快適な自社アプリを作ってみてください!

今回のコード作成にはGitHub Copilotの力を借りながら実施しました。
今後開発者がコードを書くことはどんどん減ると思いますが、参考にしてみてください。

今後も良く使う処理などあれば随時追加していきます。

26
18
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
26
18