본문 바로가기
Tips

파이썬으로 노션 데이터베이스 접근하기

by 두우우우움 2022. 8. 8.

 우리는 보통 노션을 개인적인 글을 작성하거나, 협업에서 칸반 보드를 사용하는 어떤 글을 작성하는 용도로 사용한다. 하지만, 노션은 글을 작성하는 용도 뿐만 아니라 API를 통해 데이터베이스를 모델링 실험에서 파라미터별 성능을 저장하거나 웹 서빙에서 DB로 사용할 수 있다.

 

 본인은 위와 같은 용도로 노션 데이터베이스를 사용하기 위해 노션 API를 통해 파이썬으로 데이터베이스의 요소를 가져오거나 요소를 추가하는 Cheat Sheet를  작성해보려고 한다.


 

 

0. 초기 세팅

 노션의 데이터베이스란 페이지를 다양한 형태로 모아놓은 저장소이다. 표, 보드, 타임라인, 캘린더 등의 형태로 표현할 수 있으며, 이번 글에서는 아래와 같은 표 형식을 기준으로 설명할 것이다.

 

 파이썬에서 노션 데이터베이스에 접근하려면 프라이빗 API 통합 토큰데이터베이스 ID가 필요하다.

 

프라이빗 API 통합 토큰

1. 왼쪽 이미지와 같은 노션 좌측에 위치한 메뉴바에서 설정과 멤버를 누른다.

 

2. 설정과 멤버를 누르면 나오는 창의 좌측에서 API 통합을 누른다.  

 

3. 하단에 내 API 통합 개발하기를 눌러 새 API 통합 만들기를 통해 프라이빗 API 통합 토큰을 생성한다.

 

프라이빗 API 통합 토큰 권한 부여

  데이터베이스가 존재하는 노션 페이지의 상단에 존재하는 공유를 누른 뒤, 초대를 누르면 사용자 외에 API 통합 선택하기에 방금 생성한 API 통합 토큰이 있을 것이다. 해당 통합 토큰을 누르고 초대를 다시 눌러주면 해당 토큰을 사용하여 페이지에 접근할 수 있다.

 

데이터베이스 ID

 페이지 내 데이터베이스에 마우스를 올려두면 좌측에 여섯개의 점으로 이루어진 메뉴바가 생긴다. 해당 바를 눌러 링크 복사를 누른 뒤, 링크를 확인하면 아래와 같은 형태를 가질 것이다.

https://www.notion.so/639645e464c64cb0b7dfc6e1651cd546?v=1bbba5e090a5445eaf80ae0dee5aa8c1

 위와 같이 링크에서 /와 ? 사이에 위치한 639645e464c64cb0b7dfc6e1651cd546이 해당 데이터베이스 ID를 나타낸다.


 

 

1. 데이터베이스 페이지 가져오기

import requests, json

def readDatabase(databaseId, headers):
    
    readUrl = f"https://api.notion.com/v1/databases/{databaseId}/query"

    res = requests.post(readUrl, headers=headers)
    print(res.status_code)

    data = res.json()
    with open("./db.json", "w", encoding="utf8") as f:
        json.dump(data, f, ensure_ascii=False)
        
token = "{Your Private API Token}"

databaseId = "{Your DatabaseID}"

headers = {
    "Authorization": "Bearer " + token,
    "Notion-Version": "2022-02-22"
}

readDatabase(databaseId, headers)

(requests 라이브러리를 따로 설치해야 한다.)

 

 위 코드를 돌리면 실행 결과가 출력되고 데이터베이스에서 불러온 값은 ./db.json에 저장된다. 200이 출력되면 잘 실행된 것이고 400, 404, 429가 출력되면 오류가 발생한 것이다. 오류의 내용은 res.text를 출력하여 확인할 수 있다. 참고

 

 headersNotion-Version은 현재 2022-06-28이 최신이나 2022-02-22로 해야 데이터베이스의 각 행의 값까지 불러올 수 있다. 2022-06-28부터는 안된다. 참고 Version-Changelog

 

"properties": {
    "직업": {
        "id": "F%3Enj",
        "type": "rich_text",
        "rich_text": [
            {
                "type": "text",
                "text": {
                    "content": "Data Analyst",
                    "link": null
                },
                "annotations": {
                    "bold": false,
                    "italic": false,
                    "strikethrough": false,
                    "underline": false,
                    "code": false,
                    "color": "default"
                },
                "plain_text": "Data Analyst",
                "href": null
            }
        ]
    },
    "나이": {
        "id": "los%7D",
        "type": "number",
        "number": 31
    },
    "이름": {
        "id": "title",
        "type": "title",
        "title": [
            {
                "type": "text",
                "text": {
                    "content": "John",
                    "link": null
                },
                "annotations": {
                    "bold": false,
                    "italic": false,
                    "strikethrough": false,
                    "underline": false,
                    "code": false,
                    "color": "default"
                },
                "plain_text": "John",
                "href": null
            }
        ]
    }
}

 db.json에서 각 행마다 properties 부분을 보면 값을 확인할 수 있다. 위는 데이터베이스의 가장 위의 행에 위치한 페이지의 properties만을 잘라온 것이다.

 

 각 열은 properties내의 key로 존재하며 contentnumber의 값을 보면 해당 열의 값을 확인할 수 있다. 굳이 properties의 모든 구조를 보여주는 이유는 데이터베이스에 페이지를 추가할 때, 구조를 알아야 하기 때문이다.

 예를 들어, 직업contentrich_text 안에 text 안에 위치하고 있으며 나이number는 바로 나이 안에 위치하고 있다.

 

def readDatabase(databaseId, headers):
    
    readUrl = f"https://api.notion.com/v1/databases/{databaseId}/query"

    res = requests.post(readUrl, headers=headers)
    data = res.json()
 
    if res.status_code == 200:
        for result in data['results']:
            try:
                properties = result['properties']
                col1 = properties['이름']['title'][0]['text']['content']
                col2 = properties['나이']['number']
                col3 = properties['직업']['rich_text'][0]['text']['content']
                print(f'이름: {col1}, 나이: {col2}, 직업: {col3}')
            except:
                continue
                
# 결과값
# 이름: John, 나이: 31, 직업: Data Analyst
# 이름: Max, 나이: 27, 직업: Engineer

 결과 값의 구조를 알았다면 위와 같이 데이터베이스의 페이지 값을 출력하게 함수를 작성할 수 있다.


 

 

2. 데이터베이스에 페이지 추가하기

import requests, json

def createPage(databaseId, headers, page_values):

    createdUrl = "https://api.notion.com/v1/pages"

    newPageData = {
        "parent": {"database_id": databaseId},
        "properties": {
            "이름": {
                "title": [
                    {
                        "text": {
                            "content": page_values['이름']
                        }
                    }
                ]
            },
            "나이": {
                "number": page_values['나이']
            },
            "직업": {
                "rich_text": [
                    {
                        "text": {
                            "content": page_values['직업']
                        }
                    }
                ]
            }
        }
    }

    data = json.dumps(newPageData)

    res = requests.post(createdUrl, headers=headers, data=data)

    print(res.status_code)
        
token = "{Your Private API Token}"

databaseId = "{Your DatabaseID}"

headers = {
    "Authorization": "Bearer " + token,
    "Content-Type": "application/json",
    "Notion-Version": "2022-02-22"
}

page_values = {
    '이름': 'Doom',
    '나이': 26,
    '직업': 'Data Analyst'
}

createPage(databaseId, headers, page_values)

 마찬가지로, 200이 출력되면 코드가 잘 실행된 것이다. 함수 내의 newPageData를 노션의 데이터베이스에 추가하는 것인데 newPageData의 구조를 위 불러오기에서 진행한 데이터베이스의 결과 구조와 같게 맞추어줘야 한다.

 

 headers에는 Content-Type이 추가되었는데, 이는 추가할 데이터의 구조가 json 형식이기 때문에 application/json으로 입력해주면 된다.

 

 createPage 코드를 실행시키면 위와 같이 새로운 페이지 행이 추가된 것을 확인할 수 있다.

 

 이 외에도 페이지 수정 등의 기능도 있으며, 데이터베이스의 값을 클라이언트로 Post하기 위한 DB로써의 역할도 가능하다.

 

 필자는 이 기능을 트레이딩 머신에서 주가 예측 모델의 성능과 하이퍼파라미터를 기록하고 자동매매에서 매수와 매도, 수익을 기록할 용도로 사용할 예정이다.


 

 

3. Reference

'Tips' 카테고리의 다른 글

Jupyter notebook snippets.json 위치  (0) 2022.04.11

댓글