こんばんは、本日は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データを二次利用することになるのでインターナル
としておくのが無難です。
以下のシークレット情報はNotionAPIを操作するのに必要ですので、大切に管理してください。
インテグレーションの接続
APIで操作したいページにはコネクタ
を追加する必要があります。
下図のように作成したインテグレーションを操作したいページにコネクトしてください。
ライブラリのインストール
pip install notion-client
操作対象
今回はサンプルとして以下のデータベースをPythonで操作することを想定します。
データベースID
本データベースのリンクをコピーからURLを取得して、その中からデータベースIDを抽出します。
?v=
の直前の32桁のIDとなります。
ページID
各レコードごとのページIDの取得も基本はデータベースIDの取得と同様です。
対象のページを開いて、リンクを取得して32桁のIDを取得します。
基本概念
APIで操作するときの基本となる概念としては以下を理解しておいてください。
NotionではPropertiesとChildrenの2つで構成されています。
- Properties : Title, カテゴリなどのページの付加情報
- Children : ページのメインコンテンツ
ソースコード
インスタンスの生成
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"]
データベースに新規レコードを追加する
少しコード長くなります。
各プロパティで日本語を使用している場合はエンコードした文字列を使用する必要があります。
以下のようなページが追加されます。
応用しやすいように様々な種類のプロパティやページコンテンツでも良く使う要素を入れています。
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
の力を借りながら実施しました。
今後開発者がコードを書くことはどんどん減ると思いますが、参考にしてみてください。
今後も良く使う処理などあれば随時追加していきます。