自动同步豆瓣图书封面到 Notion 的读书笔记

2023-02-12
#python #notion

TL;DR

可以通过以下脚本实现同步封面到 Notion 读书笔记

from typing import List, TypedDict
import requests
import os

database_id = os.getenv("database_id") # 读书笔记对应到数据库id
notion_version = os.getenv("notion_version", "2022-02-22") # 固定参数
token = os.getenv("token") # 自己的integrations的token

if not all([database_id, token]):
    raise ValueError("neither token or database id can't be none")

notion_headers = {
    'Authorization': f'Bearer {token}',
    'Content-Type': 'application/json',
    'Notion-Version': notion_version
}


class EmptyCoverPage(TypedDict):
    page_id: str
    book_name: str


def _get_image_from_douban(book_name: str) -> str:
    resp = requests.get(
        f'https://book.douban.com/j/subject_suggest?q={book_name}', headers={"User-Agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"})
    if resp.status_code != 200 or not resp.json():
        return
    resp_json = resp.json()
    return resp_json[0]["pic"]


def _get_pages_with_empty_cover(database_id: str) -> List[EmptyCoverPage]:
    url = f"https://api.notion.com/v1/databases/{database_id}/query"
    payload = {
        "filter": {
            "property": "封面图", # 封面列的名称
            "files": {
                "is_empty": True
            }
        }
    }
    resp = requests.post(url, json=payload, headers=notion_headers)
    if resp.status_code != 200:
        return []
    resp_json = resp.json()
    return [EmptyCoverPage(page_id=item["id"], book_name=item["properties"]["书名"]["title"][0]["text"]["content"]) for item in resp_json["results"]]


def _set_cover(cover: str, page_id: str):
    url = f"https://api.notion.com/v1/pages/{page_id}"
    payload = {
        "properties": {
            "封面图": {
                "files": [{
                    "name": cover,
                    "type": "external",
                    "external": {
                        "url": cover
                    }
                }]
            }
        }
    }
    resp = requests.patch(url, json=payload, headers=notion_headers)
    return resp.status_code == 200


def sync_covers_to_book():
    pages_with_empty_cover = _get_pages_with_empty_cover(database_id)
    print(f'当前有{len(pages_with_empty_cover)}本书没有设置封面')
    for page in pages_with_empty_cover:
        book_name = page["book_name"]
        cover = _get_image_from_douban(page["book_name"])
        if cover:
            print(f'成功获取到{book_name}的封面')
            if _set_cover(cover, page["page_id"]):
                print(f'成功设置{book_name}封面')
            else:
                print(f'设置{book_name}封面失败')
        else:
            print(f'未获取到{book_name}的封面')


if __name__ == '__main__':
    sync_covers_to_book()

前言

我一直有使用 notion 记录自己的读书笔记的习惯

读书笔记

在此之前,对应书籍的读书封面,都是我从豆瓣手动复制封面地址,然后在 notion 上设置的,这个流程太过重复和单调了,所以就考虑写个程序将这个流程自动化起来。

设置读书模版

如果需要直接使用上述脚本的话,可以直接将我的模版 Duplicate,否则的话,保留封面那一列也可以

image

⚠️封面那一列的属性为 File & media
image

创建 integrations

去 notion 创建自己的 integrations,选择对应的 workspace

截屏2023-02-12 16 07 16

其中 Capabilities 中的 Content Capabilities 三个都要勾选

image

创建完成后,会获得一个 token

image

Connect 你的 integrations

在你的图书馆 Connect 你刚才的 integrations

image

⚠️可能需要过几分钟,才能找到你创建创建的 integrations

设置程序中对应的参数

程序中的 database_id 可以在你的图书馆的 url 找到,这里以我的图书馆为例子,

https://leetao-personal.notion.site/leetao-personal/32718a67dc634ab1960b3591bc52d913

url 最后一串 uuid 就是 dababase_id,程序中的另外一个参数 token 就是刚才获取的那个 token,notion_version 暂时固定不需要调整。

最后

最后将这个脚本放到 github action 上,定时执行一下,就可以不需要人工干预,自动同步封面了;当然程序远不止可以同步封面这些,还可以同步豆瓣的评分,把你之前的阅读记录全部同步到 notion,剩下的这些就可以自己定制化开发了。