셀레니움은 프로그램을 이용해 자동화된 웹 테스트를 수행할 수 있도록 해주는 프레임워크이다.
셀레니움과 웹 드라이버를 이용하면 파이썬에서 웹 브라우저를 제어하여 컨트롤 할 수 있습니다
셀레니움과 웹 드라이버를 사용하기 위해선 일단 라이브러리 인스톨 과정이 필요합니다
pip install Selenium
pip install webdriver-manager
설치가 완료됬으면 셀레니움을 사용해봅시다
from selenium import webdriver <- 웹 브라우저와 연결
from selenium.webdriver.chrome.service import Service <- 크롬 객체생성시 필요
from webdriver_manager.chrome import ChromeDriverManager <- 크롬과 싱크를 맞추기위해 사용
필요한 라이브러리들을 import시켜줍니다
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
위 코드를 실행시키면 크롬 브라우저가 열립니다
하지만 그냥 브라우저가 열릴 뿐 평소에 열던 브라우저처럼 구글이 보이지않을 뿐만아니라 아무것도 보이지 않습니다
이제 드라이버를 이용해 주소를 여는법을 알아봅시다
driver.get("http://www.naver.com")
get을 이용하니 브라우저가 네이버로 이동하는것을 확인할수 있습니다
이번에는 켜져있는 페이지에서 화면을 html로 받아와봅시다
print(driver.page_source)
페이지 소스가 출력되는것을 확인 할 수 있습니다
작업이 끝났지만 브라우저는 그대로 켜져있습니다
이번에는 위 동작을 완료하면 창이 꺼지도록 해봅시다
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("http://www.example.com")
print(driver.page_source)
with as 구문을 사용하면 동작을 완료한후 자동으로 브라우저가 종료되는것을 확인할수 있습니다
이번에는 소스가 아닌 특정 태그의 text를 가져오는 방법을 알아봅시다
from selenium.webdriver.common.by import By
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("http://www.example.com")
print(driver.find_element(By.TAG_NAME, "p").text)
example 페이지에서 볼수있는 첫번째 p 태그를 가져와서 내용을 출력하는것을 볼수있습니다
하나의 요소를 찾을때는 셀레니움에 By를 import 시킨후
.find_element(by, target) 를 이용하면 해당 요소를 찾을수있습니다
.find_element(By.기준, target)
여러개의 요소를 가져오는방법또한 크게 다르지않습니다
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("http://www.example.com")
for el in driver.find_elements(By.TAG_NAME, "p") :
print(el.text)
하지만 list형태로 받아오기 때문에 for문을 사용해서 출력합니다
Xpath 는 XML, HTML 문서 등의 요소의 위치를 경로로 표현하는 것을 의미합니다.
웹 페이지에서 원하는 데이터의 class나 id를 특정 할 수 없을 경우
웹 페이지의 구조를 이해한 뒤 Xpath를 이용해서 원하는 데이터를 가져올 수 도 있습니다
Xpath 예시
/html/body/div/h1
비동기적 페이지에서는 원하는 정보의 위치를 특정하여 가져오고 싶어도 페이지 자체에 데이터가 도착하지않아 가져올수 없는경우가 발생할수 있습니다 이러한 경우는 wait를 이용하여 해결합니다
Implicit / Explicit Wait
Implicit Wait :정해진 시간만큼 대기
implicitly_wait()
from selenium.webdriver.support.ui import WebDriverWait
driver.implicitly_wait(20)
주의할 점으론 입력한 시간을 반드시 기다리는것이 아닌 로딩을 기다리는 한계 시간을 의미하고있습니다
Explicit Wait : 조건이 성립될때까지 대기
WebDriverWait()
from selenium.webdriver.support import expected_conditionsas EC
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "target")))
id가 target인 요소가 존재할 때까지 기다린 후 다음 명령을 진행하는 코드입니다
until() 이 아닌 until_not()을 사용한다면 해당인자가 만족되지 않을때 까지 기다리는 코드로 변경할수 있습니다
Xpath와 wait를 이용하면 비동기페이지에 대해서도 정보를 가져올수 있지만 해당방법은 결국 같은 구조를 가지지않은 페이지에서는 사용할수 없기때문에 주의해야됩니다
button = driver.find_element(By.ID, "button")
ActionChains(driver).click(button).perform()
ActionChains 를 이용하면 동작을 연속적으로 실행시켜줄수 있습니다
ActionChains와 perform사이에 동작들을 채워넣으면 그 사이의 동작들을 연쇄적으로 작동시킬수 있습니다
마우스 이벤트와 키보드 이벤트를 이용하여 네이버 로그인을 해봅시다
from selenium import webdriver
from selenium.webdriver import ActionChains
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://www.naver.com")
driver.implicitly_wait(3)
button = driver.find_element(By.CLASS_NAME, "MyView-module__my_login___tOTgr")
ActionChains(driver).click(button).perform()
성공적으로 이동하는것을 확인할수 있습니다
로그인 페이지로 이동했으면 이제 정보를 입력해야합니다
이번에는 아이디를 입력해봅시다
id_input = driver.find_element(By.ID, "id")
ActionChains(driver).send_keys_to_element(id_input, "아이디").perform()
send_keys_to_element(요소, “값”)을 이용하면 정보를 요소로 보낼수있습니다
이번에는 비밀번호를 입력해봅시다
pw_input = driver.find_element(By.ID, "pw")
ActionChains(driver).send_keys_to_element(pw_input, "비밀번호").perform()
입력을 완료했으면 로그인 버튼을 눌러줍시다
login_button = driver.find_element(By.ID, "log.login")
ActionChains(driver).click(login_button).perform()
정상적으로 로그인버튼까지 눌러졌습니다
하지만 이러한 액션들이 너무 빠르게 전환 되다 보면 웹 상에서의 이벤트가 작동하다가 오류가 발생 할 수 있습니다
이러한 문제를 해결하는 가장 간단한 방법인 행동 사이사이에 딜레이를 주는방법이 있습니다
행동 사이사이에 딜레이를 주는예시
import time
id_input = driver.find_element(By.ID, "id")
ActionChains(driver).send_keys_to_element(id_input, "아이디").perform()
time.sleep(1)
pw_input = driver.find_element(By.ID, "pw")
ActionChains(driver).send_keys_to_element(pw_input, "비밀번호").perform()
time.sleep(1)
login_button = driver.find_element(By.ID, "log.login")
ActionChains(driver).click(login_button).perform()