PythonによるNotionデータベースのページと内容を自動的に作成

# 1. 背景

最近の仕事では、ドキュメントを自動処理し、処理結果をNotionのページ内のデータベースに自動保存し、さらに結果を保存するためのNotionページを自動作成することで、業務フローを加速したいと考えていて、どのように自動化処理を進めればよいでしょうか？

以下の手順が役に立つことになるなら、嬉しいです！

# 2. Requirements

### **Notion API Key**

- 取得方法
    - [こちら](https://www.notion.so/profile/integrations)からアクセスする
        - Integration Nameを作成する
        - ワークスペースを選択した上、TypeをInternalを指定する
        
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/93acdec0-ae54-2edf-c535-e688b88c96bb.png)

        
    - Capabilitiesを以下のような形で指定する
        
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/9a7edd76-bc72-7d45-afa7-693a871489ee.png)
    - Internal Integration Secret (Notion API Key) を保存する

### データベースID と データベースコラム名

- **データベースIDは、情報を挿入したいデータベースを特定するために使用され、データベース列名は、新しく作成されるページの情報を特定するために使用されます。**
- 取得方法
    - Notionデータベースの具体的な情報を確認して直接取得
        - 操作したいNotionデータベースを開く。データベースは、独立したページでも、他のページに埋め込まれたものであっても構わない
        - Notionでは、データベースIDは通常、ブラウザのアドレスバーのURLに含まれている
        - 例えば、`https://www.notion.so/<database-id>?v=...`
            - `database-id`がデータベースID
        - データベース Property
            - 以下の図のように、Propertiesの中で、typeがTitleに対応する名前がコラム名となる
            
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/c4cad039-75b2-189e-77d8-73b2b55433e4.png)
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/42448c34-ae53-f8af-6ce6-d211894edd03.png)

            
- ページ内の内容を順番に確認して特定する
    - **すべてのデータベースをリストアップ**
        - 複数のデータベースがあり、特定のIDが不明な場合、Notion APIを使用してすべてのデータベースIDと必要な列名をリストアップできる
        - ここで注意が必要なのは、アクセスしたいページのIDをページのURLから確認できる
        - データベースIDとPropertyの調査結果が以下のようになる
         ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/df8d017e-45f0-b3b5-d601-8e1a5cd9a8d6.png)

        
    - コード
        ```notion_find_database.py
        def print_page_content(block_id, indent=0):
            page_content = get_notion_page_content(block_id)
            if page_content:
                for block in page_content['results']:
                    block_type = block['type']
                    indent_str = " " * indent
                    print(f"{indent_str}Block type: {block_type}")
        
                    if block_type == 'child_database':
                        database_id = block['id']
                        print(f"{indent_str}Found database with ID: {database_id}")
                        get_database_properties(database_id)
                    elif block_type == 'column_list' or block_type == 'column':
                        print(f"{indent_str}Processing column list or column")
                        print_page_content(block['id'], indent + 2)
                    elif 'text' in block[block_type]:
                        text = ''.join([t['plain_text'] for t in block[block_type]['text']])
                        print(f"{indent_str}Text: {text}")
                    else:
                        print(f"{indent_str}No text content")
        ```
        
        - コードでは、以下に示す同じページの中に複数列のデータの場合も考慮している
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/63c8e8d5-c854-fa3b-ba9f-3b584873c603.png)

# 3. データを新しいページを作成してインサートする

### 環境変数の設定

```notion_insert_database.py
from dotenv import load_dotenv

load_dotenv()
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
DATABASE_ID = os.getenv("NOTION_DATABASE_ID")
NOTION_API_URL = "https://api.notion.com/v1/pages"
```

### データ構成

- 以下のようにデータを構造化してInsertする

    ```notion_insert_database.py
        children_blocks = [
            {
                "object": "block",
                "type": "paragraph",
                "paragraph": {
                    "rich_text": [
                        {
                            "type": "text",
                            "text": {
                                "content": block
                            }
                        }
                    ]
                }
            } for block in content_blocks
        ]
    ```

### 新しいページを作成する

- `"名前"` はデータベース内のTypeがTitleである値に対応する
- `title` は新しいページの名前
- `toggle` は新しいページ内のデータ構成形式

    ```notion_insert_database.py
        new_page_data = {
            "parent": {"database_id": DATABASE_ID},
            "properties": {
                "名前": {
                    "title": [
                        {
                            "text": {
                                "content": title
                            }
                        }
                    ]
                }
            },
            "children": [
                {
                    "object": "block",
                    "type": "toggle",
                    "toggle": {
                        "rich_text": [
                            {
                                "type": "text",
                                "text": {
                                    "content": "transcript"
                                }
                            }
                        ],
                        "children": children_blocks
                    }
                }
            ]
        }
    ```

### 結果確認

- Codeは以下のような形

    ```notion_insert_database.py
    page_title = "New Notion Page"
    page_content = "Contents in Page" * 10
    create_notion_page(page_title, page_content)
    ```

- Toggle Listの形でまとまれてることを確認できた

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/9f78629f-0846-fa88-927c-f191fb167e4e.png)
### Code
https://github.com/yh00722/Demo_DL/tree/main/Notion