๐ Python์ผ๋ก ํ ์คํธ ์ฝ๋ ์์ฑํด๋ณด๊ธฐ
์๋ก
์ ์๊ฐ์๋ Selenium
์ ์ฌ์ฉํ๊ธฐ ์ํ ํ๊ฒฝ์ ๊ตฌ์ฑํ์๊ณ , ์ด๋ฒ ์๊ฐ์๋ ๊ตฌ์ฑ๋ Selenium
์ ์ด์ฉํด์ ์ค์ ๋ก ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์์ ๋ณผ ์์ ์ด๋ค. ๋ง์ฝ์ ํ๊ฒฝ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์ง ์ฝ์ง ์์ ๋ถ์ ์ฝ์ผ๋ฉด์ ์ฐฌ์ฐฌํ ํ๊ฒฝ์ ๊ตฌ์ฑํด๋ณด๊ธธ ๋ฐ๋๋ค.
๊ทธ๋ผ ๋ฐ๋ก ํ ์คํธ ์ฝ๋ ์์ฑ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ์!
ํ ์คํธ ํ๊ฒฝ์ ๋ค์๊ณผ ๊ฐ๋ค.
OS : Window 10 Pro
IDE : Pycharm Ultimate Edition
Python SDK : Python 3.8 (๋งํฌ๋ฅผ ๋๋ฅด๋ฉด ์ค์นํ์ด์ง๋ก ์ด๋ํฉ๋๋ค.)
Web browser : Google Chrome 90 (Chrome ๊ถ์ฅ)
Python Environment : virtualenv (pip)
๋ณธ๋ก
๋จผ์ ์์ ์ด Selenium
์ฝ๋ ์์ฑ์ ์ํด ์ฌ์ฉํ๋ IDE๋ฅผ ์คํ์ํจ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด์ ์ ๋ง๋ค์๋ ํ๋ก์ ํธ๋ฅผ ์ผ ๋ค. (ํ์๋ PyCharm
์ ์ด์ฉํ๋ค.)
์ฌ๊ธฐ์ ์ ๊น!๐
์์ฑ์ ์์์ ๋ง์ด ์ฌ์ฉ๋๋ Selenium
์ฝ๋์ ๋ํด์ ์ง๊ณ ๋์ด๊ฐ ๋ณผ ์์ ์ด๋ค.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
def main():
# ์์ ์ด ์ฌ์ฉํ๋ ์น๋๋ผ์ด๋ฒ ๊ฐ์ ธ์ค๊ธฐ
driver = webdriver.Chrome("C:/Users/junsugi/Desktop/chromedriver.exe")
# get ๋ฉ์๋๋ ํด๋น URL๋ก ์ด๋ํ๋ค.
driver.get("https://google.com")
# id๋ก element ์ฐพ๊ธฐ
driver.find_element_by_id("id")
# class๋ก ํ๋์ element ์ฐพ๊ธฐ
driver.find_element_by_class_name("className")
# class๋ก ์ฌ๋ฌ๊ฐ์ element ์ฐพ๊ธฐ
driver.find_elements_by_class_name("className")
# class ์ด์ธ์๋ name, tag name ๋ฑ ๋ค์ํ ์์๋ก element๋ฅผ ์ฐพ์ ์ ์๋ค.
# ํ์ํ ์ํฉ์ ๋ฐ๋ผ์ ์งํํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
# xpath๋ก element ์ฐพ๊ธฐ (๊ธ์์ ์์ธํ ๋ค๋ฃฐ ์์ )
driver.find_element_by_xpath("xpath")
# ํ์ด์ง ๋ก๋ฉ ๊ธฐ๋ค๋ฆด ์ ์๋๋ก ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
wait = WebDriverWait(driver, 5)
์๊ฐ๋๋๊ฑด ์ด์ ๋ ๋ฐ์ ์๋ค. ์ถ๊ฐ๋ก ๋์์ด ๋ ๋งํ ๋ด์ฉ์ด ์๊ฐํ๋ฉด ์ ์ด๋ฃ๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ณดํต Selenium
์ฝ๋๋ ์์ ์ด ๊ฐ๋ฐํ ์น ์ฌ์ดํธ ํ
์คํธ๋ฅผ ์ํด์ ์ฌ์ฉํ์ง๋ง ์ฐ๋ฆฌ๋ ์ฐ์ ์์ค์ ๋์์๋ ์ ๋ช
์ฌ์ดํธ์์ ์ด๋ป๊ฒ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋์ง๋ฅผ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค. ๋ฐ๋ผ์ ์ ๋ LostArk ๊ฒ์ ํํ์ด์ง์์ ์ ์ ๊ฒ์ ์์ด๋์ ์ ๋ณด๋ฅผ ๊ฒ์ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์๋๋ฆฌ์ค๋ก ํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ์ ๋ก์คํธ์ํฌ ๊ณต์ํํ์ด์ง์ ์ ์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ๊ฐ๋ฐ์ ๋๊ตฌ(F12) ๋ฅผ ์ผ์ ์์ ์ด ์ฐพ์์ผ ํ๋ element
๋ฅผ ์ฐพ์ต๋๋ค. ์ ๋ ์ ํฌ์ ๋ณด์ค์ด๋ผ๋ ๋ฒํผ์ element
๋ฅผ ์ฐพ๊ฒ ์ต๋๋ค.
์ฌ๊ธฐ์ ๋ด๊ฐ ์ํ๋ element
์ ์์ฑ์ ๋น ๋ฅด๊ฒ ์ฐพ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์์ด์ฝ์ด ๋ณด์
๋๋ค.
ํด๋น ์์ด์ฝ์ ๋๋ฅด๊ณ ๋ด๊ฐ ์ํ๋ element
๋ฅผ ํด๋ฆญํ๋ฉด ๊ณง๋ฐ๋ก ๊ฐ๋ฐ์๋๊ตฌ์์ ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ํ๋์์ผ๋ก ์ ํํด์ค๋๋ค.
์ด ๊ณผ์ ์ ๋จ์ถ๊ธฐ๊ฐ ์กด์ฌํ๋๋ฐ Ctrl + Shite + C
๋ฅผ ๋๋ฅด๋ฉด ์์ด์ฝ์ ๋๋ฅด์ง ์์๋ ์๋์ผ๋ก Select
๋ชจ๋๋ก ์ ํ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋์ element
๋ฅผ ํ์ธํด๋ดค๋๋ ID
๊ฐ๋ ์๊ณ Class
, Name
๊ฐ์ด ์ ๋ถ ์์ด์ ์์์ ๋ฐฐ์ด ์ฝ๋๋ก๋ element
๋ฅผ ์ฐพ์ ์๊ฐ ์๋๋ฐ, ์ด๋ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด xPath ์
๋๋ค.
๋ฐ๋ผ์ xPath
๋ฅผ ์ด์ฉํด์ ๋ค์์ element
๋ฅผ ์ฐพ์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฐพ์ ์ ์์ต๋๋ค.
character = driver.find_element_by_xpath("//nav[@class='nav']//ul//a[@href='/Profile/Character']")
character.click()
์ ์ ๋ ๊ฒ xPath
๊ฐ ์
๋ ฅ์ด ๋์๋์ง html
์ ํตํด ์ดํด๋ณด์.
์ ํฌ์ ๋ณด์ค element
๊ฐ ๋ค์ด์๋ ์ฒซ ์์ ํ๊ทธ๊ฐ div
๋ก ๋์์๋ค. ๋ฐ๋ผ์ ์ฒ์๋ถํฐ ํ๊ณ ๋ค์ด๊ฐ๋ ๋ฐฉ๋ฒ๋ ์์ง๋ง ๋๋ nav
ํ๊ทธ๊ฐ ์ด๊ณณ์์๋ง ์ฌ์ฉ๋๋๊ฑธ ๊ฐ๋ฐ์๋๊ตฌ์์ ๊ฒ์ํด์ ์์๊ณ nav
๋ถํฐ ํ๊ณ ๋ค์ด๊ฐ๋ ๋ฐฉํฅ์ผ๋ก ํํ๋ค. ๊ทธ๋ฐ๋ฐ ํ์คํ๊ฒ ๋ด๊ฐ ์ํ๋ nav
๋ก ๊ฒ์๋๊ธธ ์ํ๊ณ ๋ฐ๋ผ์ class
๋ฅผ ๋ช
์ํด์คฌ๋ค.
๋ฐ๋ผ์ //nav[@class='nav']
๋ก xPath
์ ์คํํธ๋ฅผ ๋์๋ค. ๊ทธ๋ฆฌ๊ณ nav
๋ฐ์ ์กด์ฌํ๋ ํ๊ทธ๊ฐ h2
์ ul
์ด ์๋๋ฐ h2
๋ ์ฐ๋ฆฌ์ ๋ชฉ์ ๊ณผ ์๊ด ์๋ ํ๊ทธ๋๊น ๋ฌด์ํ๊ณ ul
ํ๊ทธ๋ฅผ ์ด์ด๋ณด์. ๊ทธ๋ฌ๋ฉด ๋ง์ ๊ฐ์์ li
๋ค์ด ์๋๋ฐ ์ฐ์ ์ฌ๊ธฐ๊น์ง ํ๋ฉด //nav//ul
์ด๋ ๊ฒ ์์ฑ์ด ๋๋ค.
์ฌ๊ธฐ๊น์ง๋ ๊ทธ๋ฅ ์์ฝ๊ฒ ๋ฐ๋ผํ ์ ์๋ค. ๊ทธ ๋ค์์ ์ฌ๊ธฐ์ ํต์ฌ์ธ๋ฐ, li
๋ฅผ ํน์ ํ๊ฒ ๊ตฌ๋ถํด์ค ์ ์๋ selector
๊ฐ ์๋ค. ๊ทธ๋์ ํ์๊ฐ ์๊ฐํ ๋ถ๋ถ์ a
ํ๊ทธ์ href
๊ฐ์ผ๋ก ์ ํฌ์ ๋ณด์ค element
๋ฅผ ์ฐพ๋๋ฐฉ๋ฒ์ ๋ ์ฌ๋ ธ๋ค. ๊ทธ๋์ xPath
๋ ๋ค์๊ณผ ๊ฐ์ด ์ ํ ์ ์๋ค.
//nav[@class='nav']//ul//a[@href='/Profile/Character']
๋ฐ๋ผ์ ul
ํ๊ทธ ๋ฐ์ a
ํ๊ทธ๋ฅผ ์ฐพ๋๋ฐ href
๋ด์ฉ์ด /Profile/Character
์ธ a
ํ๊ทธ๋ฅผ ์ฐพ๊ฒ ๋ค๋ ์๋ฏธ๋ค. ์ฌ๊ธฐ์ ํ๊ฐ์ง ์ค์ํ ๋ฌธ๋ฒ์ด ๋์ค๋๋ฐ ํ๊ทธ์ด๋ฆ[@์
๋ ํฐ='๊ฐ']
์ผ๋ก ์ ์ผ๋ฉด ํด๋น element
๋ฅผ ์ฐพ์ ์ ์๋ค. ์
๋ ํฐ์๋ id
, class
, name
, href
๋ฑ ๋ค์ํ ๊ฐ์ด ์ ํ ์ ์๋๋ฐ ์์ธํ ๋ด์ฉ์ ๊ตฌ๊ธ์ ๊ฒ์ํด๋ณด๋ฉด ์ ์ ์๋ค.
๊ทธ๋์ xPath
๋ฅผ ์ต์ข
์ ์ผ๋ก ์ ์ด๋ณด๋ฉด ๋ค์ ์ฝ๋์ฒ๋ผ ์ ํ ์ ์๋ค.
character = driver.find_element_by_xpath("//nav[@class='nav']//ul//a[@href='/Profile/Character']")
character.click() # a ํ๊ทธ ํด๋ฆญํ๊ธฐ
find_elements_by_xpath
๊ฐ ์๊ณfind_element_by_xpath
๊ฐ ์๋๋ฐ ์ฐ๋ฆฌ๋ ์ ํฌ์ ๋ณด์ค ํ๋๋ง ํ์ํ๊ธฐ ๋๋ฌธ์element
๋ก ์ฌ์ฉํ๋ค. ํน์ ๋ณต์์element
๋ฅผ ์ฐพ์์ผ ํ๋ ๊ฒฝ์ฐ๋elements
๋ก ๊ฒ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์คํํ๋ฉด ์ ํฌ์ ๋ณด์ค๋ก ํ์ด์ง๊ฐ ์ด๋ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ฌ๊ธฐ์ ๋ด ๋๋ค์์ ๊ฒ์ํ๊ณ ์ ๋ณด๋ฅผ print
ํด๋ณด๋ ๋ถ๋ถ๊น์ง ์งํํด๋ณด์. xpath
๋ถ๋ถ์ด ์ค๋ช
์ด ๊ธธ์ด์ ธ์ ๊ทธ๋ฌ์ง ๋๋จธ์ง๋ ๊ธ๋ฐฉ์ด๋ค.
๋ฐ๋ผ์ ๋ค์ html
์ ๋ถ์ํด์ผ ๋๋๋ฐ ๋ด๊ฐ ๊ฐ์ ์
๋ ฅํด์ผ ๋๋ input
ํ๊ทธ element
๋ฅผ ์ฐพ์์ผ ํ๋ค.
๋ก๋ฐ์์ ใทใท ๐โโ๏ธ
๋คํ(?)์ค๋ฝ๊ฒ๋ input
ํ๊ทธ์๋ ๋ญ๊ฐ ๋ง์ด ์ ํ์๋ค. ๋ฐ๋ผ์ ์ด ๋ถ๋ถ๋ class
๋ฅผ ์ด์ฉํด์ element
๋ฅผ ์ฐพ์๋ณด๋๋ก ํ๊ฒ ๋ค. ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
input = driver.find_element_by_class_name("input--profile-search")
input.send_keys("์ ๊ฑฐ์ข")
submit = driver.find_element_by_class_name("button--profile-search")
submit.click()
send_keys
๋input
ํ๊ทธ์ ๊ฐ์ ๋ฃ์ ๋ ์ฌ์ฉ๋๋ค. (์์ธํ ๋ถ๋ถ์ ์ถํ์ ์ค๋ช )
click()
๋ฉ์๋๋ ๋ฒํผ์ ํด๋ฆญํ ๋ ์ฌ์ฉํ๋ค.
์ฌ๊ธฐ๊น์ง ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๋ง์ง๋ง์ผ๋ก ๊ฒ์๋ ๊ฐ์ print
ํด์ console
์ ์ฐ์ด๋ณด๋ฉด ๋๋๋๋ฐ, ํด๋น ๋ถ๋ถ์ ์ ๋ถ ๋ค ๋๊ฐ๊ณ .text
๋ฉ์๋๋ง ์ด์ฉํ๋ฉด ๋๋ค. ๋ฐ๋ผ์ ๊ฐ๋จํ๊ฒ ๋๋ค์ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์ค๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
name = driver.find_element_by_class_name("profile-character-info__name")
print(name.text)
์์์ ๋ณด์ผ์ง ๋ชจ๋ฅด๊ฒ ๋๋ฐ
console
์ฐฝ์ '์ ๊ฑฐ์ข' ์ด ๋ฌ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
๋ฐ๋ผ์ ์ด ๊ณผ์ ์ ์ ์ฒด ์ฝ๋๋ก ์ ์ผ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
import time
from selenium import webdriver
def print_hi():
# ์์ ์ด ์ฌ์ฉํ๋ ์น๋๋ผ์ด๋ฒ ๊ฐ์ ธ์ค๊ธฐ
driver = webdriver.Chrome("C:/Users/junsugi/Desktop/chromedriver.exe")
# get ๋ฉ์๋๋ ํด๋น URL๋ก ์ด๋ํ๋ค.
driver.get("https://lostark.game.onstove.com/Main")
character = driver.find_element_by_xpath("//nav[@class='nav']//ul//a[@href='/Profile/Character']")
character.click()
input = driver.find_element_by_class_name("input--profile-search")
input.send_keys("์ ๊ฑฐ์ข")
submit = driver.find_element_by_class_name("button--profile-search")
submit.click()
name = driver.find_element_by_class_name("profile-character-info__name")
print(name.text)
# driver session ์ข
๋ฃ
driver.close()
if __name__ == '__main__':
print_hi()
๊ฒฐ๋ก
์ต๋ํ ์ฝ๊ฒ ์ค๋ช
์ ํ๋ ค๊ณ ํ๋๋ฐ ๋ญ๊ฐ ์ค๊ตฌ๋๋ฐฉ ์ค๋ช
ํ ๊ฒ ๊ฐ์๋ค. ์ง๊ธ๊น์ง ์ค๋ช
ํ ๋ถ๋ถ์ Selenium
์ ๊ธฐ์ด์ ๊ธฐ์ด๋ง ์ค๋ช
ํ๋ค. ๋๋ ์์ง ์ ๋ฌธ์ ์ธ ์ง์์ ๊ฐ์ง๊ฑด ์์ง๋ง ์กฐ๊ธ ๋ ์์์ผ ํ ๋ถ๋ถ๋ค์ด ์กด์ฌํ๋ค.
๋๊ฒ ํ์ด์ง ๋ก๋ฉ์ด ๋๋๊ธฐ๋ ์ ์ element
๋ฅผ ์ฐพ๋ ๊ฒฝ์ฐ ์๋ฌ๊ฐ ๋จ๋๋ฐ ๊ทธ ๋ ํ์ด์ง ๋ก๋ฉ์ ๊ธฐ๋ค๋ ธ๋ค๊ฐ element
๋ฅผ ์ฐพ๋ ์์ฃผ ์ข์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค๋ ์๋ค.
์ด๋ฐ ๋ถ๋ถ๋ค์ ๋ค์ ํฌ์คํ ์์ ๋ค๋ค๋ณด๋๋ก ํ ์์ ์ด๋ค.
๋ค์ ํฌ์คํ ๋ ์ฌ๋น ๋ฅด๊ฒ ์ฌ๋ฆด ์ ์๋๋ก ๋ ธ๋ ฅํ๊ฒ ์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค.
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ Python์ผ๋ก ํ ์คํธ ์ฝ๋ ์์ฑํด๋ณด๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@junsugi/Python์ผ๋ก-ํ ์คํธ-์ฝ๋-์์ฑํด๋ณด๊ธฐ์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค