Status | Finished |
---|---|
Goal | |
Learning Stacks | |
Category | Project |
Tag | Notion2Tistory |
Tags | bs4notionnotion-pyshutiltistory |
๋์์ ์ค ์ฌ์ดํธ๋ค
- ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๋นผ๊ณ ๋ชจ๋ ๊ฒ (์ด ๋ถ์ด ํ ๊ฑธ ์กฐ๊ธ ๋ค๋ฌ์ ๋๋)
notion-py๋ก ๋ ธ์ CMS ๊ตฌ์ถํ๊ธฐ - ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ฉ
https://younho9.dev/notion-cms-using-database
์ด์ ๊ธ์์ notion-py๋ฅผ ์ฌ์ฉํด ๋ ธ์ ์ ํ์ด์ง์ ์๋ ๋ธ๋ก๊ทธ ํฌ์คํธ๋ค์ ๋งํฌ๋ค์ด ๋ฌธ์๋ก ์ถ์ถํ๋ ๋ฐฉ๋ฒ๊น์ง ์ฌ์ฉํด๋ดค๋ค. ํ์ง๋ง ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ ธ์ ์ CMS๋ก ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ ธ์ ์ ๊ฐ๋ ฅํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฅ์ ํ์ฉํ๋ ค๊ณ ํ๋ค.
๋ ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ฉํ๊ธฐ
์ด์ ๋ฐฉ์์ฒ๋ผ ํ ํ์ด์ง ์์ ๋ธ๋ก๊ทธ ํฌ์คํธ๋ค์ ๋จ์ํ ๋ชจ์๋๋ ๊ฒ์ ์ฌ๋ฌ๋ชจ๋ก ๋ถํธํ๋ค. ํฌ์คํธ์ ์ ๋ชฉ๋ง ๋ณด์ด๊ธฐ ๋๋ฌธ์, ์ธ์ ์์ฑํ๋์ง, ๋ฌด์จ ์ฃผ์ ์ธ์ง ์ฝ๊ฒ ํ์ ํ๊ธฐ ์ด๋ ต๋ค.
๋ ธ์ ์ ๋ค์ํ ์ฝํ ์ธ ๋ฅผ ๊ด๋ฆฌํ ์ ์๋ ๊ฐ๋ ฅํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฅ์ ์ ๊ณตํ๋๋ฐ, ์ด๋ฅผ ํ์ฉํ๋ฉด ๋ธ๋ก๊ทธ ํฌ์คํธ๋ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์๋ค.
๋ค์ํ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํด ์์ฑ ๋ ์ง, ์ํ, ํ๊ทธ, ์์ฑ์ ๋ฑ ๋ธ๋ก๊ทธ ํฌ์คํธ์ ํ์ํ ํค๋ ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ด๋ฌํ ํ๋กํผํฐ๋ค์ ํ์ฉํด์ ํํฐ๋งํ๊ณ ์ ๋ ฌํ๋ ๊ธฐ๋ฅ์ ์ง์ํ๋ฉฐ, ํ ์ด๋ธ, ๋ณด๋, ์บ๋ฆฐ๋ ๋ฑ ๋ค์ํ ๋ทฐ๋ฅผ ์ง์ํ๊ธฐ ๋๋ฌธ์ ์ฝํ ์ธ ๋ค์ ์ฝ๊ฒ ํ์ ํ ์ ์๋ค.
๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค (Linked database)
๋ ธ์ ์๋ ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ผ๋ ๊ฐ๋ ์ด ์๋ค. ๋ ธ์ ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ธ๋ผ์ธ ๋๋ ํํ์ด์ง๋ก ๋ง๋ค ์ ์๋๋ฐ, ์ด๋ ๊ฒ ๋ง๋ ์๋ณธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ โ๋งํฌโํ์ฌ ๋ค๋ฅธ ํ์ด์ง ์์ ๋ฃ๊ฑฐ๋, ์์ฒด ํ์ด์ง๋ก ๋ง๋๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
์๋ณธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก, ๋ฐ์ดํฐ๊ฐ ์์ ํ ๋๊ธฐํ๋๋ค.
์๋ณธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ์ด์ง์ ์ฝ์ ํ ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค. ์ผ์ชฝ์ โํ์ดํ๊ฐ ๋ณด์ธ๋ค.
๋ณธ๊ฒฉ์ ์ธ CMS ๊ตฌ์ถ
์ด๋ ๊ฒ ๊ฐ๋ ฅํ ๋ ธ์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ ธ์ CMS๋ฅผ ๊ตฌ์ถํด๋ณด์.
๋จผ์ ๋ ธ์ ์ ๋ธ๋ก๊ทธ ํฌ์คํธ๋ฅผ ๊ด๋ฆฌํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ง๋ ๋ค. ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ค์ํ ์์ฑ๊ณผ ๋ทฐ๋ฅผ ์ถ๊ฐํ์ฌ ๊ฐ์์ ๋ฐฉ์์ผ๋ก ๋ธ๋ก๊ทธ CMS๋ฅผ ๋ง๋ค ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋น ํ์ด์ง๋ฅผ ํ๋ ๋ง๋ค์ด, ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ์ถ๊ฐํ๋ค.
์ผ์ชฝ ์ฌ์ด๋๋ฐ์ ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฐํด๋ฆญํ์ฌ ๋งํฌ๋ฅผ ๋ณต์ฌํ๊ณ ํ์ด์ง์ ๋ถ์ฌ๋ฃ๊ธฐํ๋ฉด ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ฝ์ ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค
id
๊ตฌํ๊ธฐ์์์ ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ด์ง์ ์ฝ์ ํ ๊ฒ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์
id
๋ฅผ ๊ตฌํ๊ธฐ ์ํด์์๋ค.์ด์ ๊ธ์ ์ฝ๋์์๋ ํ์ด์ง์
url
๋ก ์ ๊ทผํด ํ์ด์ง ๋ด์ ํฌ์คํธ์ ์ ๊ทผํ ๊ฒ์ด๋ค. ํ์ง๋ง ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ ํฌ์คํธ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด์๋ ํ์ด์ง์url
์ด ์๋๋ผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์id
๊ฐ ํ์ํ๋ค.์๋ณธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋์ผํ
id
๋ฅผ ๊ฐ์ง๋ฏ๋ก ์ด์ ์ ์์ฑํ ์ฝ๋๋ฅผ ํ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์คid
๋ฅผ ๊ตฌํ ์ ์๋ค.๋ฐ์ดํฐ๋ฒ ์ด์ค์
id
๋ ์๋์ ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํ ์ ์๋ค.token_v2
๋ ์์ ์token_v2
๊ทธ๋๋ก ์ฌ์ฉํ๋ฉด ๋๊ณ , ๋งํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ธ๋ญ์ ํฌํจํ๊ณ ์๋ ํ์ด์ง์url
์ ๋ฃ์ด, ํ์ด์ง ์์ ์๋ ๋ธ๋ญ๋ค์ ์ถ๋ ฅํด๋ณด๋ฉด, ๋ธ๋ญ์id
, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ชฉ, ๋ฐ์ดํฐ๋ฒ ์ด์ค(collection
)์id
๊ฐ ์ถ๋ ฅ๋๋ค.3from notion.client import NotionClient5 client = NotionClient(token_v2="NOTION_TOKEN") 6page = client.get_block("NOTION_PAGE_URL")8 for block in page.children :9 print(block)
์ด ์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด,
block
์id
์collection
์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ์ดํ๊ณผid
๋ฅผ ์ถ๋ ฅํ๋ค. ์ดcollection
์id
๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ ์ ์๋ค.๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํฌ์คํธ์ ์ ๊ทผํ๊ธฐ
์ด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํด ๊ธ์ ๊ฐ์ ธ์ค๋๋ก ์ฝ๋๋ฅผ ์์ ํ์. notion-py์์๋
get_collection(collection_id)
๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๊ฐ๊ณ ์๋ ์ ๋ณด๋ค์ ๊ฐ์ ธ์ฌ ์ ์๊ณ ,collection.get_rows()
๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฐ ํ์ ์๋ ํฌ์คํธ์ ์ ๊ทผํ ์ ์๋ค.3from notion.client import NotionClient5client = NotionClient("NOTION_TOKEN")6contents_collection = client.get_collection("COLLECTION_ID")7posts = contents_collection.get_rows()9for post in posts:10 print(post)
์ด์ ์ด๋ ๊ฒ ์ ๊ทผํ ํฌ์คํธ์ ๋ด์ฉ์ ๊ฐ์ ธ์ค๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
6from notion.client import NotionClient8client = NotionClient("NOTION_TOKEN")9contents_collection = client.get_collection("COLLECTION_ID")10posts = contents_collection.get_rows()12for post in posts:14 text = """---18---""" % (post.title, datetime.datetime.now())20 text = text + '\n\n' + '# ' + post.title + '\n\n'21 for block in post.children:23 if (block.type == 'header'):24 text = text + '# ' + block.title + '\n\n'26 if (block.type == 'sub_header'):27 text = text + '## ' + block.title + '\n\n'29 if (block.type == 'sub_sub_header'):30 text = text + '### ' + block.title + '\n\n'32 if (block.type == 'code'):33 text = text + '```\n' + block.title + '\n```\n'35 if (block.type == 'image'):36 text = text + '![' + block.id + '](' + block.source + ')\n\n'38 if (block.type == 'bulleted_list'):39 text = text + '* ' + block.title + '\n\n'41 if (block.type == 'divider'):42 text = text + '---' + '\n\n'44 if (block.type == 'text'):45 text = text + block.title + '\n\n'46 title = post.title.replace(' ', '-')47 title = title.replace(',', '')48 title = title.replace(':', '')49 title = title.replace(';', '')50 title = title.lower()52 os.mkdir('../content/blog/' + title)55 file = open('../content/blog/' + title + '/index.md', 'w')57 print(text)58 file.write(text)
๋ฐ์ดํฐ๋ฒ ์ด์ค์
property
๊ฐ์ ธ์ค๊ธฐ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ง์ ํ ์์ฑ๋ค ์ญ์ ๊ฐ์ ธ์ ํ์ฉํ ์ ์๋ค. ์๋ฅผ ๋ค์ด ์์ฑ ์๋ฃ๋ ํฌ์คํธ๋ง ๊ฐ์ ธ์จ๋ค๊ฑฐ๋, ํฌ์คํธ์ ์์ฑ ๋ ์ง๋ ํ๊ทธ๋ค์ ๊ฐ์ ธ์ ํค๋๋ฐ์ดํฐ๋ก ์ฌ์ฉํ๋ ๋ฑ์ผ๋ก ํ์ฉํ ์ ์๋ค.
6from notion.client import NotionClient8client = NotionClient("NOTION_TOKEN")9contents_collection = client.get_collection("COLLECTION_ID")10properties = contents_collection.get_schema_properties()12for property in properties:13 print(property)
๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๊ฐ๊ณ ์๋ ์์ฑ๋ค์ ๋ชฉ๋ก์
collection
์get_schema_properties()
๋ฅผ ์ฌ์ฉํ์ฌ ํ์ธํ ์ ์๋ค.์ด
property
๋ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์๋ ๊ฐ๊ฐ์ ํฌ์คํธ๊ฐ ๊ฐ๊ณ ์๋ค.post.status
,post.tags
๋ฑ ์๋์์slug
์ ๊ฐ์ผ๋ก ํฌ์คํธ์property
์ ์ ๊ทผํ ์ ์๋ค.๐ค ์ ๊ธฐํ๊ฒ๋, ํ๊ธ ์์ฑ์ ๋ฐ์๋๋ก ์์ด๋ก ๋ฐ๋์ด ๋ํ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๋ค.
์ด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํฌ์คํธ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ํฌ์คํธ๊ฐ ๊ฐ๊ณ ์๋ ์์ฑ๋ ๊ฐ์ ธ์ฌ ์ ์๋ค.
6from notion.client import NotionClient8client = NotionClient("NOTION_TOKEN")9contents_collection = client.get_collection("COLLECTION_ID")10posts = contents_collection.get_rows()12for post in posts:13 print(post.tags)
์ถ๊ฐ ์ค์
๋จธ๋ฆฌ๋ง ๊ตฌ์ฑ
์ด๋ ๊ฒ ๊ฐ์ ธ์จ ์์ฑ๋ค์ ๋ธ๋ก๊ทธ ํฌ์คํธ์ ๋จธ๋ฆฌ๋ง ๋ฐ์ดํฐ๋ก ์ฌ์ฉํด๋ณด์.
hero : ์ธ๋ค์ผ ์ด๋ฏธ์ง excerpt : ์์ฝ ๋ฌธ๊ตฌ
๋ด๊ฐ ์ฌ์ฉํ๊ณ ์๋ Gatsby ๋ธ๋ก๊ทธ์์๋ ์ด๋ฌํ ๋จธ๋ฆฌ๋ง ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํค๋๋ฅผ ์ํ ๋ฐ์ดํฐ๋ค์ ์ถ๊ฐํด์ฃผ์๋ค.
์ด์ ๊ฐ ์์ฑ์
slug
๊ฐ์ผ๋ก ์ ๊ทผํ์ฌ ๋จธ๋ฆฟ๋ง์ ์ถ๊ฐํ๋ฉด ๋๋ค.4from notion.client import NotionClient6client = NotionClient("NOTION_TOKEN")7contents_collection = client.get_collection("COLLECTION_ID")8posts = contents_collection.get_rows()10for post in posts:12 text = """---17""" % (post.title, post.author, post.created_time.strftime("%Y-%m-%d"), post.excerpt)18 if not post.hero:19 text = text + '---\n\n'20 elif 'png' in post.hero[0]:21 text = text + 'hero: ' + './images/hero.png\n---\n\n'22 image_format = 'png'23 elif 'jpg' in post.hero[0]:24 text = text + 'hero: ' + './images/hero.jpg\n---\n\n'25 image_format = 'jpg'27 print(text)
์ฌ๊ธฐ์
hero
์ฆ, ์ปค๋ฒ ์ด๋ฏธ์ง ํ์ผ์ ๋ํ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค. ๋ ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ ์คFiles & media
๋ ์ด๋ฏธ์ง์ ํ์ผurl
์ด ๋ฌธ์์ด๋ก ๋ด๊ธด ๋ฐฐ์ด์ ์ฌ์ฉํ๋๋ฐ,url
์ ์๋ ์ด๋ฏธ์ง ํ์ผ ํ์์์ ๋ฐ๋ฅธ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์๋ค.์ดํ์ ์ด ์ด๋ฏธ์ง ๋งํฌ์์ ์ด๋ฏธ์ง๋ฅผ
./image/hero.xxx
๊ฒฝ๋ก์ ๋ค์ด๋ฐ์ ๊ฒ์ด๋ค.๋จธ๋ฆฟ๋ง์ด ์ ๊ตฌ์ฑ๋์๋ค.
๋ ๋ง์ ๋ ธ์ ๋ธ๋ก ํ์ ์ง์ํ๊ธฐ
์ด์ ๊ธ์ ์ฝ๋์์๋ ๋ค์ํ ๋ ธ์ ๋ธ๋ก์ ๋ํ ์ง์์ด ๋ถ์กฑํ๋ค.
์ฌ๋ฌ ๋ธ๋ก ํ์ ์ ๋ํ ์ฒ๋ฆฌ๋ ๊ฐ๋จํ๊ฒ
block.type
์ผ๋กtype
์ ์์๋ด๊ณblock.title
๋ก ์ ๊ทผํด ๋ด์ฉ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.1for post in posts:3 text = """---8""" % (post.title, post.author, post.created_time.strftime("%Y-%m-%d"), post.excerpt)9 if not post.hero:10 text = text + '---\n\n'11 elif 'png' in post.hero[0]:12 text = text + 'hero: ' + './images/hero.png\n---\n\n'13 image_format = 'png'14 elif 'jpg' in post.hero[0]:15 text = text + 'hero: ' + './images/hero.jpg\n---\n\n'16 image_format = 'jpg'19 text = text + '\n\n' + '# ' + post.title + '\n\n'20 for block in post.children:21 print(block.type)22 print(block)
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋จํ๊ฒ
block
์ ํ์ ์ด๋ฆ๊ณผtitle
์ ์ด๋ค ๋ด์ฉ์ด ๋ด๊ธฐ๋์ง ๋ณผ ์ ์์๋ค.block
ํ์ ๋ณ๋ก ์ด๋ค ์ถ๊ฐ์ ์ธ ์์ฑ์ ๊ฐ์ง๋์ง๋ ์์ ์์ค๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ค.์๋ฅผ ๋ค์ด
callout
๋ธ๋ญ์icon
์์ฑ์ ๊ฐ๊ณ ,code
๋ธ๋ญ์language
์์ฑ์ ๊ฐ๊ณ ,bookmark
๋ธ๋ญ์link
,bookmark_cover
๋ฑ์ ์์ฑ์ ๊ฐ๋๋ค.์ด๋ฐ ์์ฑ๋ค์ ํ์ฉํ๋ฉด ๋ณด๋ค ์ ํํ๊ฒ ๋ ธ์ ๋ธ๋ก๊ทธ ๊ธ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
์ฌ์ง์ด ๋ ธ์ ์์ฒด ๋งํฌ๋ค์ด export ๊ธฐ๋ฅ์ ์ธ์ด ์ง์ ์ด ๋ฐ์๋์ง ์๋๋ฐ language ์์ฑ์ผ๋ก ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ ์ ์๋ค.
1for post in posts:3 text = """---8""" % (post.title, post.author, post.created_time.strftime("%Y-%m-%d"), post.excerpt)9 if not post.hero:10 text = text + '---\n\n'11 elif 'png' in post.hero[0]:12 text = text + 'hero: ' + './images/hero.png\n---\n\n'13 image_format = 'png'14 elif 'jpg' in post.hero[0]:15 text = text + 'hero: ' + './images/hero.jpg\n---\n\n'16 image_format = 'jpg'19 text = text + '# ' + post.title + '\n\n'20 for block in post.children:22 if (block.type == 'header'):23 text = text + '# ' + block.title + '\n\n'25 if (block.type == 'sub_header'):26 text = text + '## ' + block.title + '\n\n'28 if (block.type == 'sub_sub_header'):29 text = text + '### ' + block.title + '\n\n'31 if (block.type == 'code'):32 text = text + '```' + block.language.lower() + '\n' + block.title + '\n```\n\n'34 if (block.type == 'callout'):35 text = text + '> ' + block.icon + ' ' + block.title + '\n\n'37 if (block.type == 'quote'):38 text = text + '> ' + block.title + '\n\n'40 if (block.type == "bookmark"):41 text = text + "๐ [" + block.title + "](" + block.link + ")\n\n"43 if (block.type == 'image'):44 text = text + '![' + block.id + '](' + block.source + ')\n\n'46 if (block.type == 'bulleted_list'):47 text = text + '* ' + block.title + '\n\n'49 if (block.type == 'divider'):50 text = text + '---' + '\n\n'52 if (block.type == 'text'):53 text = text + block.title + '\n\n'
callout
,code
,bookmark
,quote
์ ๋ํ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค. ๋ ๋ง์ ์ฝ๋๋ ๊ณ์ ์ถ๊ฐํ ์์ ์ด๋ค.์ปค๋ฒ ์ด๋ฏธ์ง ๋ค์ด๋ฐ๊ธฐ
์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์
hero
์์ฑ์ ์ถ๊ฐํcover
์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ์.2import urllib.request6for post in posts:11 title = post.title.replace(' ', '-')12 title = title.replace(',', '')13 title = title.replace(':', '')14 title = title.replace(';', '')15 title = title.lower()18 os.mkdir('../content/blog/' + title)23 if post.hero:25 os.mkdir('../content/blog/' + title + '/images')28 if 'png' in post.hero[0]:29 urllib.request.urlretrieve(post.hero[0], "../content/blog/" + title + "/images/hero.png")30 elif 'jpg' in post.hero[0]:31 urllib.request.urlretrieve(post.hero[0], "../content/blog/" + title + "/images/hero.jpg")33 file = open('../content/blog/' + title + '/index.md', 'w')35 print(text)36 file.write(text)
ํฌ์คํธ ์ ๋ชฉ์ ๋ฐ๋ผ ํด๋๋ฅผ ๋ง๋ค๊ณ , ํฌ์คํธ ํด๋ ์์
images
ํด๋์hero
์ด๋ฏธ์ง๋ฅผurllib.request
๋ฅผ ์ฌ์ฉํด ๋ค์ด๋ฐ์๋ค. ์์ธํ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ์.์ํ๋ ์์น์ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํ๋ค. ๋จธ๋ฆฌ๋ง์
hero
์ ๊ฒฝ๋ก๊ฐ ์ง์ ๋์ด ์์ผ๋ฏ๋ก Gatsby ๋ธ๋ก๊ทธ์์๋ ์ด ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ ์ปค๋ฒ๋ก ์ฌ์ฉํ ๊ฒ์ด๋ค.๋ง์น๋ฉฐ
์ด๋ ๊ฒ notion-py๋ฅผ ํ์ฉํ์ฌ ๋ ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ ๋งํฌ๋ค์ด ๋ฌธ์๋ค์ ๋ก์ปฌ๋ก ๊ฐ์ ธ์๋ค.
๋ ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ฉํ๋ฉด ๋ค์ํ๊ฒ ๋ทฐ๋ฅผ ๋ฐ๊ฟ๊ฐ๋ฉฐ ์ฝํ ์ธ ๋ฅผ ํ์ธํ ์ ์๊ณ ,
sort
,filter
๋ฑ์ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค. ๋ํ ์์ฑ์ ํ์ฉํ์ฌ ๊ธ์ ๋ถ๋ฅํ๊ณ ๊ด๋ฆฌํ๋ ๋ฑ CMS๋ก ํ์ฉํ ์ ์๋ค.๋ฌผ๋ก ์์ ์ฝ๋๋ ๋งํฌ๋ค์ด ๋ฌธ์๋ก ์ถ์ถ๋๊ธฐ ๋๋ฌธ์ ๋งํฌ๋ค์ด์ ์ง์ํ๋ ๋ธ๋ก๊ทธ ํ๋ซํผ์ด ์๋๋ผ๋ฉด ์์ ์ด ํ์ํ๋ค. ํ์ง๋ง ์ฝ๋๋ฅผ ์กฐ๊ธ๋ง ์์ ํด๋ ์ด๋ค ๋ธ๋ก๊ทธ ํ๋ซํผ์ ์ ์ฉํ ์ ์๋ค.
๋ค์ ๊ธ์์๋
- os์ ํ๊ฒฝ๋ณ์์
token_v2
๋ฅผ ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ
config.py
์collection_id
๋ฅผ ์ ์ฅํ๊ณ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ
- ๋
ธ์
๋ฐ์ดํฐ๋ฒ ์ด์ค์
status
์ ๋ฐ๋ผ ์ฝํ ์ธ ๋ฅผ ํํฐ๋งํ์ฌ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ
- ๋ ธ์ ์์ ๊ธ ์์ฑ์ด ์๋ฃ๋์์ ๋ Github์ ์๋์ผ๋ก ์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ
๋ค์ ๋ค๋ค๋ณผ ์์ ์ด๋ค.
notion-py๋ ๋น๊ณต์ ๋ ธ์ API์ด๋ค
๋ฌผ๋ก notion-py๊ฐ โ๋น๊ณต์โ ๋ ธ์ API์ด๊ณ , ๋ ธ์ ์์๋ ๊ณง ๊ณต์ API๋ฅผ ์ถ์ํ ์์ ์ด๋ผ๊ณ ํ๊ธฐ ๋๋ฌธ์, ์ด API๋ฅผ ์ธ์ ๊ฐ ์ฌ์ฉํ์ง ๋ชปํ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
ํ์ง๋ง notion-py๋ฅผ ๋ค๋ฃจ๋ฉฐ ๋ ธ์ ๊ณต์ API๊ฐ ๊ฐ์ ธ์ฌ ์ด๋ง์ด๋งํ ๊ฐ๋ฅ์ฑ์ ๋ํด ์๊ฐํด ๋ณผ ์ ์์๋ค. ๋ ธ์ ์ด ์ ๋ง โAll-In-One Workspaceโ ๊ฐ ๋ ์ ์์๊น?
๋น ๋ฅธ ์์ผ ๋ด ๊ณต์ API๊ฐ ์ถ์๋๊ณ ๋ง์ ์ ์ ๋ค์ด ์ฌ์ฉํ๋ฉด์ ์๋ง์ ํ์ฉ ์์ ๋ค์ด ํ์ํ๊ธธ ๊ธฐ๋ํ๋ค.
- os์ ํ๊ฒฝ๋ณ์์
์๋ฌ ๊ด๋ จ
notion-py๋ก ๋ ธ์ CMS ๊ตฌ์ถํ๊ธฐ - ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ฉ์ ์ฌ๋ณธ Got 400 error attempting to POST to queryCollection ยท Issue #350 ยท jamalex/notion-py ยท GitHub - notion-py ๊ฐ ๋ง์ ์๋ฃ๋ ์ด์ ์๋ค.
์ฝ๋๋ฅผ ์ฌ์ฉํ๋ ๊ณผ์
main.py
์ฝ๋๋ฅผ ๋ค์ด๋ก๋ํ์ฌ workspace ์ ๊ฐ์ ธ๋ค์ค๋๋ค. ํน์ ์์ github ์ ๋ชจ๋ ๋ค์ด๋ฐ์ ์ฌ์ฉํด๋ ๋ฉ๋๋ค.- ํด๋ ๊ตฌ์กฐ
- workspace
- main.py
- upload (folder)
- ์ ๋ก๋ ํ ํ์ผ๋ค
- workspace
- ํด๋ ๊ตฌ์กฐ
- ๋
ธ์
๊ฒ์๋ฌผ ์ค๋นํ๊ธฐ (๋
ธ์
์ ๋ชฉ์ ํ๊ธ์ด ํฌํจ๋์ด ์์ผ๋ฉด ์ ์๋ฉ๋๋ค.)
- ๊ธ์ ์ฌ๋ฐ๋ฅธ ์์ฑ ๋ถ์ฌํ๊ธฐ
- ํ์์ ์ธ ์์ฑ
Category
: ํฐ์คํ ๋ฆฌ์ ์กด์ฌํ๋ ์นดํ ๊ณ ๋ฆฌ์ ๋ง๊ฒ ์์ฑ
- ๋น ํ์์ ์ธ ์์ฑ
Tag
: ํฐ์คํ ๋ฆฌ ๊ธ์ ์ถ๊ฐํ ํ๊ทธ
Tags
: ํฐ์คํ ๋ฆฌ ๊ธ์ ์ถ๊ฐํ ํ๊ทธ๋ค- ๋ ๊ฐ๋ฅผ ๋๋ ์ด์ ๋ ํ์๊ฐ, ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ํ์ด ํ ๊ฒ๋ค์ ์นดํ
๊ณ ๋ฆฌ๋ก ๋ถ๋ฅํ ๋,
์ฌ์ดํธ/์ค์ฌ tag
๋ก ๋๋์ด ์ผ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ ๊ฐ ๋ค ์์ด๋ ์๋์ ํฉ๋๋ค.
- ๋ ๊ฐ๋ฅผ ๋๋ ์ด์ ๋ ํ์๊ฐ, ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ํ์ด ํ ๊ฒ๋ค์ ์นดํ
๊ณ ๋ฆฌ๋ก ๋ถ๋ฅํ ๋,
- ํ์์ ์ธ ์์ฑ
- ๊ธ์ ์ฌ๋ฐ๋ฅธ ์์ฑ ๋ถ์ฌํ๊ธฐ
- ๋
ธ์
๊ฒ์๋ฌผ ๋ค์ด๋ก๋ํ๊ธฐ
- ํด๋น ๊ฒ์๋ฌผ์ ๋ค์ด๊ฐ์, ์ฐ์ธก ์๋จ์ ์ค์ ์ ํด๋ฆญํฉ๋๋ค.
- HTML ํ์์ผ๋ก ๋ด๋ณด๋ ๋๋ค.
c. ์๊น ๋ง๋ค์ด๋ upload ํด๋์ ๋ค์ด๋ก๋ ๋ฐ์ ํด๋๋ฅผ ๋ถ์ฌ๋ฃ์ต๋๋ค.
๐ก์ฌ๋ฌ ๊ฐ ๋์์ ๋ฃ์ด๋ ๊ฐ๋ฅํฉ๋๋ค.๐ก๋ ธ์ ์์ html ์ export ํ ๋ mac ์์, ์ด๋ ๊ฒฝ์ฐ์๋ zip ์ผ๋ก, ์ด๋ ๊ฒฝ์ฐ์๋ ํด๋๋ก ๋ฐ๋ก ๋ค์ด๋ฐ์์ก์ต๋๋ค. ์ฝ๋๋ฅผ ํต์ผํ๊ธฐ ์ํด์, zip ํ์ผ ์์ฒด๋ฅผ ๋ฃ๋ ๊ฒ์ด ์๋๋ผ zip ์ ์์ถ ํ์ด ์ค ๋ค์, ํด๋ ํ์์ผ๋ก upload ํด๋์ ๋ฃ๋๋ก ํฉ๋๋ค.
main.py
์config
์ค์ ํ๊ธฐ- 5๊ฐ์ ๋ณ์๊ฐ ์์ต๋๋ค.
config = { "ACCESS_TOKEN" :"์์ ์ tistory access token", "BLOG_NAME" : "์์ ์ tistory ๋ธ๋ก๊ทธ ์ด๋ฆ", "REMOVE_AFTER_UPLOAD" : ์ ๋ก๋ ํ ๋ค์ ํ์ผ์ ์ญ์ ํ๋ ค๋ฉด True, ์๋๋ฉด False "upload_path" : "์์ ์ `upload` ํด๋์ ๊ฒฝ๋ก (์ ๋ ๊ฒฝ๋ก๋ก ํ๋ ๊ฒ ๋ง์ ํธํจ)", "CODE_AS_PYTHON" : ์ฝ๋ ํ์ด๋ผ์ดํธ๋ฅผ python ์ผ๋ก ํต์ผํ๋ ค๋ฉด True, }
ACCESS_TOKEN
์ ์ด๋ป๊ฒ ์ป์๊น?
- 5๊ฐ์ ๋ณ์๊ฐ ์์ต๋๋ค.
๊ฒช์๋ ๋ฌธ์ ํด๊ฒฐ ๊ณผ์
์ด๋ฏธ์ง ๊นจ์ง ๋ฌธ์ ํด๊ฒฐํ๊ธฐ
๐ก๋ก์ปฌ ํ์ผ์์ ๋ ธ์ ์ ์ด๋ฏธ์ง ํ์ผ์ ์ฌ๋ฆฌ๊ณ ํด๋น ํ์ด์ง๋ฅผ tistory ์ ์ฌ๋ ค๋ณด๋ฉด ์ด๋ฏธ์ง๊ฐ ์์ด์ง๋ค. ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น?์ ๊ทธ๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋๊ฐ
- ๋ ธ์ ์์ HTML ๋ก ๋ด๋ณด๋ด๋ฉด ํด๋น ํ์ด์ง์ img ๊ฐ ์์์ ๊ฐ์ด ๋ค์ด๋ก๋ ๋๋ค.
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, HTML ์์์์ img ์ src tag ์์ฑ์ ๋ก์ปฌ ํ์ผ ๊ฒฝ๋ก๊ฐ ๋๋ค.
- ์ด๊ฒ์ ๋ฐ๋ก Tistory API ๋ก ๋ณด๋ด๋ฒ๋ฆฌ๋ฉด ๋น์ฐํ, ๋ก์ปฌ ํ์ผ์ด ์๊ธฐ ๋๋ฌธ์ ์๋๋ค.
ํด๊ฒฐ์ฑ
- ๋
ธ์
์์ HTML ๊ณผ ๊ฐ์ด ๋ค์ด๋ฐ์ img ํ์ผ์
base64
ํํ๋ก ๋ฐ๊พธ์ด ๊ทธ๋๋ก img ์ src์ ๋ฃ๋๋ค.
# img base64๋ก ๋ณํํ์ฌ ์ ๋ก๋ all_img_columns = article.find_all('img') img_columns = [] for i, img_column in enumerate(all_img_columns): if not ('http' in img_column['src'] or 'ico' in img_column['src']): img_columns.append(img_column) if img_columns != 0: for img_column in img_columns: modified_img_path = img_column['src'].replace("%5B", '[').replace("%5D", ']').replace("%20", ' ') im_b64 = base64.b64encode( open(f"{path_list[html_idx]}/{modified_img_path}","rb").read() ).decode('utf-8') img_column['src'] = f"data:image/png;base64,{im_b64}"
์ ๋ก๋ํ ํ์ผ ์ญ์ ํ๊ธฐ
os.rmdir
์ ๋น์ด์๋ ํด๋๋ง ์ญ์ ํด์ค์,shutil.rmtree
๋ฅผ ์ฌ์ฉํ๋ค.
notion ์์ export ํ ์์,
[]|()
๊ฐ์ ํน์๋ฌธ์๋ค์ด%20
%30
๊ฐ์ ๊ฒ๋ค๋ก ๋ณํ๋์ด์, ๊ฒฝ๋ก ์ฐพ๊ธฐ๊ฐ ํ๋ค์๋ ๋ฌธ์ - ์ ๋ง.. ํ๋์ฝ๋ฉ ๊ทธ์์ฒด ํด๋ฒ๋ ธ์ต๋๋ค.. ํ๋ํ๋ ํ๋ฆฐํธ ํด๊ฐ๋ฉด์ ์ด๋ค ํน์๋ฌธ์๊ฐ ์ด๋ป๊ฒ ๋ณํ๋๋์ง ์ฐพ์ ๋ค์, ์ด๋ฐ ์์ผ๋ก ๋ณํ ์์ผฐ์ต๋๋ค. ๋ง์ฝ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ๋ด๊ฐ ๋ณํํด๋์ง ์์ ํน์๋ฌธ์๋ฅผ ์ ๋ชฉ์ ์ฌ์ฉํ๋์ง ํ ๊ฒ์ผ ๊ฒ๋๋ค.
modified_img_path = img_column['src'].replace("%5B", '[').replace("%5D", ']').replace("%20", ' ')
๊ฐ์ฅ ํ๋ค์๋.. tistory ์ css ์ notion css ๋ง์ถ๊ธฐ
Notion์์ Tistory๋ก ์๋ ์ ๋ก๋ #4 (notion css style ์ ์ฉ)Notion์์ Tistory๋ก ์๋ ์ ๋ก๋ #4 (notion css style ์ ์ฉ) ์ง๋ ๋ฒ์ notion page๋ฅผ htmlํํ๋ก exportํ์ฌ python์ผ๋ก parsingํ๊ณ tistory API๋ก ์ง์ ์ ๋ก๋๊น์ง ํด๋ณด์์ต๋๋ค. ์ด๋ฒ์๋ notion CSS๋ฅผ ์ ์ฉํ์ฌ ๋ธ๋ก๊ทธ์์๋ ๋ ธ์ ๊ณผ ๊ฐ์ style๋ก ๋ณด์ด๊ฒ ์์ ํด๋ณด๊ฒ ์ต๋๋ค. ์๋๋ notion page๋ฅผ html exportํ ํ์ผ์ ์ด์์ ๋์ ์์ค ์ ๋๋ค. ํ๊ทธ ์์ ์ฌ๋ฌ๊ฐ์ง css๊ฐ ์ ํ ์๋๋ฐ์, ์ด๋ฅผ ํฐ์คํ ๋ฆฌ ๋ธ๋ก๊ทธ์ ๊ทธ๋๋ก ๊ฐ์ ธ๊ฐ๋ฉด ์ ์ฉ์ด ๋ฉ๋๋ค.https://minimin2.tistory.com/101- ์ด ๋ถ์ ๋๋ถ์ ์ฌ๋งํ ๊ฒ๋ค์ ๋ค ์ ์์ ์ผ๋ก ์๋ํ์ง๋ง, ๊ฐ์์๊ฒ ์ ์ฉ๋๋ ์คํจ์ด ๋ค๋ฅด๊ณ ํ๋ค ๋ณด๋, ๋์๊ฒ ๋ง๋ css ๋ฅผ ์์ฑํ๊ธฐ๊ฐ ์ฝ์ง ์์์ต๋๋ค.
- ์ tistory ์คํจ๊ณผ css ๋ชจ๋ ๊ณต์ ํด๋๋ฆดํ ๋, ์คํจ ์์ฒด๋ฅผ ๋ฐ๊พธ์ค ๋ถ์ ์ ์ฉํ๋ฉด ์ ๋ธ๋ก๊ทธ๋์ ๋๊ฐ์ด ๋ ๊ฒ๋๋ค. github ์ ์ ๋ก๋ํด๋์์ต๋๋ค.
๐ก์ ๋ CCZ-CROSS ์คํจ์ ๊ธฐ๋ณธ์ผ๋ก ํ์ฌ ํธ์งํ์์ต๋๋ค.
Mac ์
.DS_Store
ํ์ผ ์ ๊ฑฐํ๊ธฐ- Mac ์ ํด๋์๋
DS_Store
๋ผ๋ ํ์ผ์ด ์๊ฒ๋ชจ๋ฅด๊ฒ ์์ต๋๋ค. ์ด๊ฑธ ์ ๊ฑฐ ์ํ๊ณ ํ๋ค๊ฐ ์ค๋ฅ๊ฐ ๋ฌ์์ต๋๋ค.
- Mac ์ ํด๋์๋
details
ํ๊ทธ์ open attribute ์ ๊ฑฐํ๊ธฐ- details ํ๊ทธ ๋ค์ด ์ฎ๊ฒจ์ง ๋ค์, ๋ค ์ด๋ ค์์ด์ ๋ณด๊ธฐ ์ซ์๋ค.
bs4
๋ก ๊ฐ๋จํ ํด๊ฒฐํ๋ค.
Tistory API ๊ณต๋ถํ๊ธฐ
visibillity
์์ ์ ๋จน์์๋ค. ์ ์ง ๋ชจ๋ฅผ ์ค๋ฅ๊ฐ ๋ง์๋ค.
โญ๏ธโญ๏ธโญ๏ธ๋ ธ์ ์์ ์ ๋ชฉ ํ ๊ธ 1,2,3 ๊ฐ ์ถ๊ฐ๋จ์ ๋ฐ๋ผ, ๊ธฐ๋ฅ ์ถ๊ฐโญ๏ธโญ๏ธโญ๏ธ
๐ก๋ ธ์ ์์์๋ ๋น์ฐํ ๋ฌธ์ ๊ฐ ์์์ผ๋, export ํ์ฌ html ์์์ ๋ณด์์ ๋๋ notion ์์ฒด์ ์ธ css ๋ ์ฌ๋ผ์ง๊ณ ํด์, toggle ์ ๊ธฐ๋ฅ๋ ํ์ง ๋ชปํ์ ๋ฟ๋๋ฌ, toggle ์ ์์น๋ ๋ง์ง ์์๋ค.- ์ด๋ป๊ฒ html ์ด ๊นจ์ ธ์, toggle ์ด ์๋์ด ์๋๋์ง ํ์
ํ๋ค.
- ์ ๋ชฉ h1
- details
- summary
- details
div class=โindentedโ
์ฌ๊ธฐ์ toggle ์์ ์ด ๋ด์ฉ์ด ๋ค์ด๊ฐ
- ์ ๋ชฉ h1
- ๋ผ๊ณ ๊นจ์ก๋ค. ์๋๋
- ์ ๋ชฉ h1
- details
- summary
div class=โindentedโ
- details
- ์ ๋ชฉ h1
- ์ด ๋์ด์, h1 ์๋์ ๋ด์ฉ์ด ์ ์ถ๋ ฅ๋์ด์ผ ํ๋ค.
- ๋ ํ๋์ ๋ฌธ์ ๋, ๋ชจ๋๊ฐ h1 ์๋์ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ํฐ ๊ธ์จ๋ก ์ถ๋ ฅ๋๋ค๋ ์ ์ด๋ค. ๊ทธ๊ฒ์ ์ํ์ง๋ ์๋๋ค.
- ๊ทธ๋์ ๋๋ ์ด๋ฐ ๊ตฌ์กฐ๋ฅผ ์๊ฐํ๋ค.
- details
- summary
- h1
- ์ ๋ชฉ
- h1
div class=โindentedโ
- summary
- details
- ํด๊ฒฐ๋ฒ
indented
๋ผ๋ class ๋ฅผ ๊ฐ์ง ๋ชจ๋ div ๋ฅผ ๊ฐ์ ธ์จ๋ค.
- h1 ์ด๋ฉด์, ์์์ด summary ์ธ ๋ชจ๋ h1 ์ ๊ฐ์ ธ์จ๋ค.
- ์์ h1 ๋ค์ ๋ชจ๋ ์ํํ๋ฉด์, ์์ ๋ฐ๋ก ๋ค์์ ํ์ ๊ฐ
<div class=โindented
โ ๋ผ๋ฉด- ๋ฐ๋ก ์๋์ details ํ๊ทธ๋ฅผ ์ฐพ์๋ธ๋ค.
- ํด๋น details ํ๊ทธ์ ์๊น ์ฐพ์๋ธ
indented div
๋ฅผ ์์์ ๋ง๊ฒ ์ถ๊ฐํ๋ค.
- details ์์ summary ๋ฅผ h1 ์ผ๋ก ๋ฌถ์ด์ค๋ค.
- ๋ฌถ์ด์ฃผ๋ฉด์,
Notion_summary_h1
์ด๋ผ๋ class ๋ฅผ ์ถ๊ฐํ์ฌ
- tistory ๋ด์์ css ์กฐ์์ด ํธํ๊ฒ ๋ง๋ ๋ค.
- ๋ฌถ์ด์ฃผ๋ฉด์,
- ์์ h1 ๋ค์ ๋ชจ๋ ์ํํ๋ฉด์, ์์ ๋ฐ๋ก ๋ค์์ ํ์ ๊ฐ
- h1 h2 h3 ์ ๋ํด์ ์คํํด์ค๋ค.
# indented block ๊ฐ์ ธ์ค๊ธฐ indented_divs = article.find_all('div', 'indented') # h1 ์ด๋ฉด์ ์์์ด summary ๊ฐ์ ธ์ค๊ธฐ all_h1 = article.find_all('h1') all_indent_h1 = [] for idx, h1 in enumerate(all_h1): if '<details>' in str(all_h1[idx]): all_indent_h1.append(all_h1[idx]) for h1_idx, indent_h1 in enumerate(all_indent_h1): for idx, sibling in enumerate(all_indent_h1[h1_idx].next_siblings): # ๋ฐ๋ก ๋ค์์ ํ์ ๊ฐ indented div ๋ผ๋ฉด if idx == 0 and '<div class="indented"' in str(sibling): details = all_indent_h1[h1_idx].find("details") details.append(sibling) summary = details.find("summary") summary.name = "h1" summary.wrap(soup.new_tag('summary', **{'class':'Notion_summary_h1'})) all_indent_h1[h1_idx].unwrap() # h2 ์ด๋ฉด์ ์์์ด summary ๊ฐ์ ธ์ค๊ธฐ all_h2 = article.find_all('h2') all_indent_h2 = [] for idx, h2 in enumerate(all_h2): if '<details>' in str(all_h2[idx]): all_indent_h2.append(all_h2[idx]) for h2_idx, indent_h2 in enumerate(all_indent_h2): for idx, sibling in enumerate(all_indent_h2[h2_idx].next_siblings): # ๋ฐ๋ก ๋ค์์ ํ์ ๊ฐ indented div ๋ผ๋ฉด if idx == 0 and '<div class="indented"' in str(sibling): details = all_indent_h2[h2_idx].find("details") details.append(sibling) summary = details.find("summary") summary.name = "h2" summary.wrap(soup.new_tag('summary', **{'class':'Notion_summary_h2'})) all_indent_h2[h2_idx].unwrap() # h3 ์ด๋ฉด์ ์์์ด summary ๊ฐ์ ธ์ค๊ธฐ all_h3 = article.find_all('h3') all_indent_h3 = [] for idx, h3 in enumerate(all_h3): if '<details>' in str(all_h3[idx]): all_indent_h3.append(all_h3[idx]) for h3_idx, indent_h3 in enumerate(all_indent_h3): for idx, sibling in enumerate(all_indent_h3[h3_idx].next_siblings): # ๋ฐ๋ก ๋ค์์ ํ์ ๊ฐ indented div ๋ผ๋ฉด if idx == 0 and '<div class="indented"' in str(sibling): details = all_indent_h3[h3_idx].find("details") details.append(sibling) summary = details.find("summary") summary.name = "h3" summary.wrap(soup.new_tag('summary', **{'class':'Notion_summary_h3'})) all_indent_h3[h3_idx].unwrap()
- ์ด๋ป๊ฒ html ์ด ๊นจ์ ธ์, toggle ์ด ์๋์ด ์๋๋์ง ํ์
ํ๋ค.
ํ๊ณ์ ๋ฐ ๋ฐ์ ์ฌํญ
- ์ฌ์ ํ ๋ง์ง ์๋ css ๋ค
details
ํ๊ทธ ๋ผ๋ ์ง, ์์ํ margin ๊ณผ padding ๋ค ๊ผด๋ณด๊ธฐ ์ซ๋ค.details
ํ๊ทธ๋ ์ฌํ๋ฆฌ์์๋ ์ ์ ์๋ํ๋๋ฐ, ํฌ๋กฌ์์๋ ํ์ดํ๊ฐ ์๋ณด์
- zip ํ์ผ๊ณผ ํด๋๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ ๋ก๋ ์์ผ๋ณด๊ธฐ
- ์ผ์ผ์ด ์์ผ๋ก export ํด์ผํ๋ ๋ถํธํจ
- selenium ์ ํ์ฉํด ํด๊ฒฐ ๊ฐ๋ฅ
- ํ์ง๋ง, notion-py ๊ฐ ๋ง์ฝ์ด์ด์ ์๋ํ์ง ์์
- selenium ์ ํ์ฉํด ํด๊ฒฐ ๊ฐ๋ฅ
Watchdog
์ ์ฌ์ฉํด์ ํด๋ ๊ฐ์ํ์ฌ ์๋ ์ ๋ก๋ ํด๋ณด๊ธฐ
- ์์ ํ๋ ค๋ฉด, ๋ ธ์ ์์ ์์ ํด์ ๋ค์ ๋ด๋ณด๋ด๊ธฐ ํด์ ๋ค์ ์ฝ๋ ๋์์์ผ์ผํจ.
- ์ ๋ชฉ์ ํ๊ธ ํฌํจ๋์ด์์ผ๋ฉด ์ ์๋จ.
- ์ฌ์ ํ ๋ง์ง ์๋ css ๋ค
'Project' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React TS Masterclass (0) | 2022.05.10 |
---|