前言
交完論文盲審稿,終於從接近一年的實習、秋招和論文的忙碌中閒下來。
在覆盤秋招的時候發現自己雖然看過不少書,但缺少整理和思考,所以想趁這個機會梳理一下自己的閱讀習慣,希望以後再讀新的東西可以更系統高效。但是手動輸入圖書資訊實在太慢了。經過一番調研,我發現有外掛Notion Plus可以匯出豆瓣圖書列表,但似乎缺少維護(我沒試),以及我自己想體驗一下Notion API,就動了寫一個小程式的念頭。在這裡把搭建過程分享給大家,全當拋磚引玉。
使用場景 : 將單本圖書資訊從豆瓣匯入到Notion database
建立Notion機器人
想要利用Notion提供的API對自己WorkSpace中的block進行操作的話,首先需要建立機器人(integration),併為機器人授予所需要操作的block操作許可權。在 我的機器人 頁面可以快速建立機器人。
建立新的機器人
填完資訊點選建立之後,系統跳轉到新的頁面。頁面最上方給出了這個機器人的Secrets ( 就是 Bearer token),點選Show可以檢視和複製。這個token會一直在這個頁面,所以不用擔心忘記。
建立資料表並邀請機器人
Notion 其實是提供了建立Database的API的,但我之前其實已經手動建立過了,所以這裡就偷懶沒寫程式碼。我的資料表長這個樣子:
設計資料表
想偷懶的同學可以直接用我的模板:閱讀清單
做好資料表之後需要邀請機器人,並授權:
獲取豆瓣讀書資料
Notion API提供的是基於RESTful架構的介面,雖然官方文件提供的是JavaScript樣例,但我自己寫Python比較多,所以還是用Python進行開發,還有一個原因就是Python爬取豆瓣資料會更加容易。
def getInfo(url):
header={
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8',
'Connection': 'keep-alive',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.235'
}
r = requests.get(url=url, headers=header)
soup = BeautifulSoup(r.text, 'lxml')
# get info
info = {}
info['title'] = soup.h1.span.text
infos = soup.find(id='info').find_all('span',attrs={'class':'pl'})
for i in infos:
if i.text.strip() == '作者':
info['作者'] = i.next_sibling.next_sibling.text
elif i.text == '出版社:':
info['出版社'] = i.next_sibling.next_sibling.text
else:
info[i.text.strip().strip(':')] = i.next_sibling.text.strip()
info['score'] = soup.find(class_='rating_num').text.strip()
info['cover'] = soup.find(class_='nbg')['href'].strip()
return info
獲取資料的程式非常簡單,requests傳送請求,BeautifulSoup解析html。這個函式需要的引數url就是豆瓣讀書某本書詳情頁面的連結,如:
資料寫入Notion
到這一步其實才開始用Notion API,簡單來說就是構造請求,POST到指定的API就可以新建一條記錄了。其中,構造請求的關鍵在於構造各欄位(Property)。Notion中各類Property的values可以從property-value-object 中找到詳細資訊。比如Database的Name欄位屬於Title property,構造方式如下:
{
"Name": {
"title": [
{
"type": "text",
"text": {
"content": "The title"
}
}
]
}
}
這裡有一個小技巧,就是可以先通過程式查詢指定頁面中各欄位的值來獲取頁面結構,然後直接修改相應的值就可以了。查詢指定頁面的欄位結構,可以構造如下請求:
import requests
token = '***'
database_id = '***'
r = requests.request(
"POST",
"https://api.notion.com/v1/databases/" + database_id + "/query",
headers={"Authorization": "Bearer " + token, "Notion-Version": "2022-02-22"},
)
print(r.text)
其中,token 就是上文建立機器人時Notion自動分配的Secrets ,database_id 就是需要查詢的頁面的id,頁面的id可以直接從連結中找到,下如紅框中的一串(從 / 到 ?中間 )就是id。
我擷取了查詢請求返回值的幾個Property:
"頁數": {
"id": "U_TO",
"type": "number",
"number": 528
},
"書名": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "切爾諾貝利的午夜",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "切爾諾貝利的午夜",
"href": null
}
]
},
"封面": {
"id": "jZol",
"type": "files",
"files": [
{
"name": "https://img1.doubanio.com/view/subject/l/public/s33836089.jpg",
"type": "external",
"external": {
"url": "https://img1.doubanio.com/view/subject/l/public/s33836089.jpg"
}
}
]
},
我們可以直接將對應的值替換成我們之前獲取到的資訊。這裡面有很多欄位是我們不需要的,比如“id”,或者"annotations" 。Notion會幫我們自動補全。
我構建的完整的Property如下:
body = {
"parent": { "type": "database_id", "database_id": database_id},
"properties": {
"書名": {
"type": "title",
"title": [{"type": "text", "text": {"content": info.get("title",' ')}}]
},
"豆瓣連結": {
"url": url
},
"ISBN": {
"type": "rich_text",
"rich_text": [{"type": "text", "text": {"content": info.get("ISBN",'')}}]
},
"頁數": {
"number": int(info.get("頁數",0))
},
"出版社": {
"type": "rich_text",
"rich_text": [{"type": "text", "text": {"content": info.get("出版社",' ')}}]
},
"評分": {
"number": float(info["score"])
},
"作者": {
"type": "rich_text",
"rich_text": [{"type": "text", "text": {"content": info.get('作者','')}}]
},
"標籤": {
"type": "multi_select",
"multi_select": [{"name": info.get('tag')}]
},
"封面": {
"files": [
{
"type": "external",
"name": info['cover'],
"external": {"url": info['cover']}
}
]
},
"狀態": {
"type": "select",
"select": {
"name": info.get('status'),
}
},
},
}
之後將這個Body作為請求的主體傳送到相應的Notion API就可以在我們的資料表中新增一條新的記錄啦。
re = requests.request(
"POST",
"https://api.notion.com/v1/pages",
json= body,
headers={"Authorization": "Bearer " + token, "Notion-Version": "2022-02-22"},
)
完整程式碼可以從我的Github獲得:Notion_douban
效果
最終的效果如下:
還可以新增一個Gallery View: