์ฒ์ ์ด ๋งคํฌ๋ก๋ฅผ ๊ฐ๋ฐํ๊ธฐ๋ก ๋ง์ ๋จน์ ๊ฒ์ DX ์ํค์ ์๋ฃ๋ฅผ ์ฌ๋ฆฌ๊ณ ๋ณด๋ velog์๋ ๋ฐ๋ก ์ฌ๋ ค์ ์๋ฃ๋ฅผ ์ ๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค๋ ์๊ฐ์ด ๋ค์์ ๋์ ๋๋ค.
๋ ๊ฐ์ ์ํค๋ฅผ ์์ฑํ๊ณ velog์ ์ฎ๊ธฐ๋ ค๊ณ ํ๋ ๋ฌผ๋ก ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐ๊ฐ ๋์ด์ง๋ง ๊ทธ ๊ณผ์ ์ญ์ ๊ท์ฐฎ๊ฒ ๋๊ปด์ก์ต๋๋ค. python ์ผ๋ก ๋งคํฌ๋ก ๋ฐ ์น ์คํฌ๋ฉ์ด ๊ฐ๋ฅํ๋ ๋ง๋ค์ด ๋ณผ ์ ์๊ฒ ๋ค ๋ผ๋ ์๊ฐ๊ณผ ํจ๊ป ๋ฐ๋ก ์์ ์ ์์ ํ์ต๋๋ค.
python ์ผ๋ก ๊ฐ๋ฅํ๋ค๋ ๊ฑด ์์์ง๋ง python ์ ์ฌ์ฉํด๋ณธ ๊ฑด ์๊ณ ๋ฆฌ์ฆ ํ ๋ ๋ฟ์ด๋ผ ๊ตฌ๊ธ์ ๋ง์ด ์ฐพ์๋ดค์ต๋๋ค. ๊ทธ์ค์ ๋์ ๋ค์ด์จ ๊ฒ์ ์ด๋์ ๋ค์ด๋ณธ ์ ์ด ์๋ selenium ์ ๋๋ค.
selenium์ ์ด์ฉํด notion์ ์ด์ด์ ๋ด์ฉ์ ๊ธ์ด์ค๊ณ ๋ค์ velog๋ฅผ ์ด์ด ๋ด์ฉ์ ๋ถ์ฌ๋ฃ๋ ๋ฐฉ์์ ์๊ฐํ์ต๋๋ค.
ํ์ง๋ง selenium์ ๊ฒฝ์ฐ ๊ฐ์์ ์น์ ์คํํ๊ธฐ ๋๋ฌธ์ ๋ก๊ทธ์ธ๋ถํฐ ๋ค์ํด์ผ๋๋ค๋ ๊ฒ์ ์์๊ณ ,
๋ก์ง์ ์์๋ก๋
- notion ๋ฐ velog ๋ก๊ทธ์ธ์ ์งํํ๋ค. ์ด ๊ณผ์ ์์ ์๋ฃ์ *.pkl ์ด๋ผ๋ ํ์ผ์ด ์์ฑ ๋๋๋ฐ ์ด ํ์ผ์๋ ๋ก๊ทธ์ธ ์ฑ๊ณต ์งํ์ cookie ๊ฐ์ด ๋ค์ด์๊ธฐ ๋๋ฌธ์ ํ ํฐ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ( ๋๋ฌธ์ .exe ํ์ผ๊ณผ *.pkl ํ์ผ์ ๊ฐ์ ๊ฒฝ๋ก(ํด๋) ์ ์์ด์ผ ํฉ๋๋ค.)
- ํ์๋ GUI์ ๋์จ๋ฐ๋ก notin url ์ ๋ ฅ ํ ๋ฒํผ ํด๋ฆญ์ notion ๋ฐ์ดํฐ ๋ณต์ ๊ฐ ์ด๋ฃจ์ด์ง๋๋ค.
- ์๋ฃ๊ฐ ๋๋ฉด .exe ํ๋ก๊ทธ๋จ์์ ๋ก๊ทธ์ธํ ๊ณ์ ์ velog์ ์ ์ํด ์์์ ์ฅ ํญ์ ํ์ธํ๋ฉด ๋ฉ๋๋ค.
selenium์ ์ด์ฉํด ์ ๋ ฅ๋ notion url ์ ์ ์ํด ๋ณธ๋ฌธ์ div์ ์ ๊ทผํ๊ณ ํด๋น div ๋ฅผ ์ ์ฒด ๋ณต์ฌ๋ฅผ ์งํํฉ๋๋ค. ๊ทธ ์ ์ title ๊ฐ์ ์ฝ์ด์ ๋ฐ๋ก ๋ณ์์ ์ ์ฅํด์ค๋๋ค.
๋ณธ๋ฌธ์ ๋ด์ฉ์ ๊ธ์ด์์ ์งํํ๋ ค ํ์ง๋ง ๊ทธ๋ด ๊ฒฝ์ฐ markdown์ ๋ฌธ๋ฒ์ด ์ ์ฉ๋์ง ์์. ๋ง์ ์ด๋ ค์์ด ์์์ต๋๋ค.
ํ์ฌ ๋ณธ๋ฌธ์ ๋ณต์ฌํ๋ค
velog.io/write ์ ์ ์ํ์ฌ title ๋ณ์์ ๋ด์ฉ์ ์ ๋ชฉ์ผ๋ก ์ ๋ ฅํ๊ณ ,
selenium ์ ํจ์๋ฅผ ์ด์ฉํด ๋ณธ๋ฌธ์ div ๋ฅผ click() ํ์ actions ์ chain์ ์ด๊ธฐํํด์ฃผ๊ณ ๋ถ์ฌ๋ฃ๊ธฐ ์์ ์ ์งํํด์ค๋๋ค.
๊ทธ ๋ค selenium์ ์ด์ฉํด ๊ฐ์ ธ์จ ์์์ ์ฅ ๋ฒํผ์ click() ์ ์ด์ฉํด ๋๋ฌ์ค ๋ค ์ฐฝ์ ๋ซ์ต๋๋ค.
selenium์ ์น ์คํฌ๋ฉํ ๋ฅ๋ ฅ์ด ๋งค์ฐ ๊ฐ๋ ฅํ๋ค๋ ๊ฒ์ ์๊ฒ๋ ์์ ์ด์์ต๋๋ค.
์ด๊ฒ ๊ฐ๋ฅํ๊ฐ ํ๊ณ ์์์ผ๋ก ์๊ฐํ ๊ธฐ๋ฅ์ด ๋๋ถ๋ถ ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด ๋๋ผ์ ์ต๋๋ค.
- ~~selenium์ ์ด์ฉํด ๋ณต์ฌํ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ฌ๋ฃ๊ธฐํ๋ ๊ฐ๋จํ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง๊น์ง ๊ฐ๋ฅํ์ง๋ ์์ ๋ณด์ ๋๋ค.
๋ฌผ๋ก ์ด๋ฏธ์ง url ์ ์ ๋๋ก ๊ฐ์ ธ์ค์ง๋ง notion์ ๋ณด์ ์ ์ฑ ์ธ์ง notion์ s3 ์ ์ ๋๋ก ์ ๊ทผ์ ๋ชปํ์ฌ ์ด๋ฏธ์ง๊ฐ ์ ๋์จ๋ค๊ณ ์๊ฐ๋ฉ๋๋ค.~~
- ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค์ง๋ง ์ ํํ ์์น์ ์ฝ์ ์ ์ด๋ ต์ต๋๋ค. ๋ฌผ๋ก ๊ณ ์น๋ ค ๋ ธ๋ ฅ์ ํด๋ณด๊ฒ ์ต๋๋ค.
- Velog์ ๊ฒฝ์ฐ์๋ git ๋ง notion ์ ๊ฒฝ์ฐ์๋ ์ง์ ์ด๋ฉ์ผ์ ์ ๋ ฅํ ๊ฒฝ์ฐ์๋ง ๋ก๊ทธ์ธ์ด ๊ฐ๋ฅํฉ๋๋ค. selenium์ ํ๊ณ์ ์ผ๋ก ๋ณด์ ๋๋ค๋ง ์๋ฃ๋ฅผ ๋ ์ฐพ์๋ณด์์ผ๊ฒ ์ต๋๋ค.
notionCookies = None
velogCookies = None
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
service = Service(executable_path=ChromeDriverManager().install())
file_paths = []
notionMainLink = "https://www.notion.so/"
def notion():
global file_paths
if entryNotionURL.get() != "" and notionMainLink in entryNotionURL.get():
urlCautionContent.set("")
driver = webdriver.Chrome(service=service, options=options)
file = "notion.pkl"
fileVelog = "velogGitLogin.pkl"
if os.path.exists(file):
notionCookies = pickle.load(open(file, "rb"))
driver.get(notionMainLink)
driver.delete_all_cookies()
for cookie in notionCookies:
# cookie.pop("domain")
driver.add_cookie(cookie)
# https://www.notion.so/ryudomain/c4828705de9e41e2b35bae5691cb7a81?pvs=4
# https://www.notion.so/mirimdxlab/Sentry-73f05aa15fdb454a9290f4b5fc6e6f47?pvs=4
driver.get(entryNotionURL.get())
driver.implicitly_wait(120)
if velogTitleEntry.get() == "":
title = driver.find_element(By.CSS_SELECTOR, '[placeholder="์ ๋ชฉ ์์"]').text
else:
title = velogTitleEntry.get()
contents = driver.find_elements(By.CLASS_NAME, 'notion-page-content')
for c in contents:
for c2 in c.find_elements(By.CLASS_NAME, "notion-selectable"):
c2.send_keys(Keys.CONTROL + 'a')
c2.send_keys(Keys.CONTROL + 'c')
for c in contents:
for c2 in c.find_elements(By.TAG_NAME, "img"):
if "notion.so" in c2.get_attribute("src"):
file_paths.append(c2.get_attribute("src"))
driver.close()
driver = webdriver.Chrome(service=service, options=options)
if os.path.exists(fileVelog):
velogCookies = pickle.load(open(fileVelog, "rb"))
driver.get("https://velog.io")
driver.delete_all_cookies()
for cookie in velogCookies:
driver.add_cookie(cookie)
driver.get("https://velog.io/write")
driver.implicitly_wait(120)
velogTitle = driver.find_element(By.CSS_SELECTOR, '[placeholder="์ ๋ชฉ์ ์
๋ ฅํ์ธ์"]')
velogTitle.send_keys(title)
velogTag = driver.find_element(By.CSS_SELECTOR, '[placeholder="ํ๊ทธ๋ฅผ ์
๋ ฅํ์ธ์"]')
velogTag.send_keys("Notion2Velog")
velogTag.send_keys(Keys.ENTER)
velogContent = driver.find_elements(By.CLASS_NAME, "CodeMirror")
for v in velogContent:
v.click()
actions = ActionChains(driver)
actions.key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL)
actions.key_down(Keys.ENTER).key_up(Keys.ENTER)
actions.perform()
for f in file_paths:
driver2 = webdriver.Chrome(service=service, options=options)
if os.path.exists(file):
notionCookies = pickle.load(open(file, "rb"))
driver2.get(notionMainLink)
driver2.delete_all_cookies()
for cookie in notionCookies:
# cookie.pop("domain")
driver2.add_cookie(cookie)
driver2.get(f)
c = driver2.find_element(By.TAG_NAME, "body")
c.send_keys(Keys.CONTROL + 'c')
actions.click()
actions.perform()
actions.key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL)
actions.perform()
driver2.close()
velogContent2 = driver.find_element(By.CLASS_NAME, "CodeMirror")
wait = WebDriverWait(driver, 10) # ์ต๋ 10์ด ๋์ ๊ธฐ๋ค๋ฆผ (ํ์์ ๋ฐ๋ผ ์กฐ์ )
def check_url(driver):
return "์
๋ก๋์ค.." not in velogContent2.text
# ์กฐ๊ฑด ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๋ค๋ฆฌ๊ธฐ
wait.until(check_url)
testSave = driver.find_elements(By.CLASS_NAME, "icODNG")
for btn in testSave:
btn.click()
time.sleep(0.5)
driver.close()
driver.quit()
driver2.quit()
file_paths = []
successCheck.set(" ์์์ ์ฅ ์ฑ๊ณตํ์ต๋๋ค.")
elif entryNotionURL.get() == "" or "https://www.notion.so/" not in entryNotionURL.get():
successCheck.set("")
urlCautionContent.set("notion url ์ ์
๋ ฅํ์ธ์.")
# pyperclip.copy(content2)
def velogGitHubLogin():
driver = webdriver.Chrome(service=service, options=options)
try:
driver.get("https://v2.velog.io/api/v2/auth/social/redirect/github?next=/&isIntegrate=0")
# ๋ก๊ทธ์ธ ํ ๋ฆฌ๋๋ ํธ๋ ์์ URL
redirected_url = "https://velog.io/"
wait = WebDriverWait(driver, 120)
# ๋ฆฌ๋๋ ํธ๋๋ ๋์ ๊ธฐ๋ค๋ฆฌ๊ธฐ
wait.until(EC.url_to_be(redirected_url))
if driver.current_url == redirected_url:
pickle.dump(driver.get_cookies(), open("velogGitLogin.pkl", "wb"))
checkVelogLogin.set("True")
finally:
# ์์
์๋ฃ ํ ๋๋ผ์ด๋ฒ ์ข
๋ฃ
driver.quit()
def notionLogin():
print(entryNotionURL.get() == "")
driver = webdriver.Chrome(service=service, options=options)
notionLoginUrl = "https://www.notion.so/login"
try:
driver.get(notionLoginUrl)
# ๋ก๊ทธ์ธ ํ ๋ฆฌ๋๋ ํธ๋ ์์ URL
redirected_url = "https://www.notion.so/"
wait = WebDriverWait(driver, 120)
def check_url(driver):
return redirected_url in driver.current_url and notionLoginUrl not in driver.current_url
# ์กฐ๊ฑด ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๋ค๋ฆฌ๊ธฐ
wait.until(check_url)
if redirected_url in driver.current_url and driver.current_url != notionLoginUrl :
pickle.dump(driver.get_cookies(), open("notion.pkl", "wb"))
checkNotionLogin.set("True")
finally:
# ์์
์๋ฃ ํ ๋๋ผ์ด๋ฒ ์ข
๋ฃ
driver.quit()
- ๋ช ํํ ํ๊ณ์ ์ด ์์ผ๋ ๊ฐ์ ํด ๋๊ฐ ์๊ฐ์ ๋๋ค. ์ด๋ฏธ์ง๋ ๋ฌผ๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ํ๊ณ์ ๊น์ง ๊ฐ์ ํด๋ณผ ์๊ฐ์ ๋๋ค.
- ์ง๊ธ ์๊ฐํ๋ ์ถ๊ฐ ๊ธฐ๋ฅ์
์ ๋ชฉ ์ ๋ ฅ๋ฐ์ velog ์์์ ์ฅ ๋ ์ฌ์ฉํ๊ธฐ ( ๋น ๋ฌธ์์ด์ ๊ฒฝ์ฐ notion์ ๋ฐ์ดํฐ ์ฌ์ฉ)- ๋ธ๋ผ์ฐ์ ์ค์ ๋ก ๋์ฐ์ง ์๊ณ ์คํํ ์ ์๋ ๋ฒ ์์๋ณด๊ณ ( chrome add argument ์คํจ )
- ์๋ ๊ฐ์
- ๊น readme ์๋ ์ฎ๊ธฐ๊ธฐ..?
- etcโฆ
๊ฐ ์์ต๋๋ค.