이전 학습으로 동적 웹사이트는 브라우저의 자동화가 필요함을 알게 되었고 이를 해결하고자 파이썬 라이브러리인 Selenium에 대해 간단히 알아보았다.
오늘은 selenium을 직접 구현해보면서 작동 방식에 대해 알아보고자 한다.
웹 브라우저와의 연동을 위해 WebDriver가 필요하고, WebDriver란 웹 브라우저를 제어할 수 있는 자동화 프레임워크이다.
selenium은 웹 브라우저를 연동해서 활용하기에 받아온 응답으로부터 특정 element를 추출할 수 있다. 요소를 찾는 함수로는 다음을 사용한다.
- find_element(By, target) : By는 대상을 찾는 기준으로 ID, TAG_NAME, CLASS_NAME이 속하고 target은 대상의 속성이다
- find_elements(By, target) : 요소 여러개 찾기 (결과가 리스트로 나오기에 for루프로 각 요소별 text화 필요)
< 구현 코드 >
# selenium으로부터 webdriver 모듈을 불러옵니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# Webdriver.Chrome을 통해 ChromeDriver객체 생성
# 아래 코드 실행을 통해 크롬 브라우저를 실행할 수 있고 파이썬과 연동 가능, url 활용 가능
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
url = 'http://www.example.com'
driver.get(url)
# 크롬 브라우저와 계속 연동하며 해당 page_source (HTML 코드) 확인 가능
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get(url)
print(driver.page_source)
# 크롬 창이 계속 뜨는 걸 방지 (scraping 용도로 확인 위해 아래 with ~ as 문 활용)
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get('http://www.example.com')
print(driver.page_source)
# Driver에서 elements 찾기, By 모듈 사용해주기
from selenium.webdriver.common.by import By
url = 'http://www.example.com'
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get(url)
# p 태그에 해당하는 요소 하나를 찾아봅시다.
print(driver.find_element(By.TAG_NAME, 'p').text)
# p 태그에 해당하는 요소 여러개를 찾아봅시다. (결과는 리스트이기에 .text적용 X)
for element in (driver.find_elements(By.TAG_NAME, 'p')):
print('Text :', element.text)
selenium은 동적 웹사이트에 대한 지원을 진행하기 위해 explicit wait와 implicit wait를 지원한다.
- Explicit wait : 로딩이 전부 될 때까지 지정된 시간 동안 기다림
- Implicit wait : 특정요소에 대한 제약을 통해 기다림 (A 태그 가져올 때까지 대기)
-> 💡 웹 브라우저와의 연동으로 제어가 가능하기에 wait역시 가능!✨ 동적 웹사이트에 그냥 get이후 특정 요소를 불러온다면?
# 라이브러리 호출 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager # XPath는 XML, HTML 문서 등의 특정 요소의 위치를 경로로 표현하는 것을 의미 url = 'https://indistreet.com/live?sortOption=startDate%3AASC' xpath = '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]' # 비동기 처리로 처음으로 페이지 열면 시간이 좀 걸리고, # get 이후 요소 찾는 과정에서 특정 요소들은 업데이트 이전의 로딩 되기에 element가 없다고 나오게 됌. driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver.get(url) driver.find_element(By.XPATH, xpath).text
💡 이를 해결하고자 진행하는 것이 wait !
1. implicitly_wait(지연시간) # : 이때 지연시간은 해당 시간을 반드시 기다리는 것이 아닌 로딩이 다 진행되기까지의 한계시간을 의미 from selenium.webdriver.support.ui import WebDriverWait with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver: driver.get(url) driver.implicitly_wait(10) # 스크래핑 할 목록: 예시 사이트의 첫 번째 이벤트의 제목(xpath로 지정한 특정요소)을 가져오기 print(driver.find_element(By.XPATH, xpath).text) 2. explicitly_wait(지연시간) # > until(): 인자의 조건이 만족할 때까지 / until_not(): 인자의 조건이 만족되지 않을 때까지 # Explicit Wait를 활용해서 스크래핑이 잘 이루어지도록 코드를 작성해봅시다. from selenium.webdriver.support import expected_conditions as EC with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver: driver.get(url) # XPATH가 xpath인 요소가 존재할 때까지 기다린 후 다음 명령 진행 element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath))) print(element.text)
from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 10개의 이벤트의 제목 출력 with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver: driver.get(url) driver.implicitly_wait(10) for i in range(1, 11): element = driver.find_element(By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[{}]/div/a/div[2]/p[1]'.format(i)) print(element.text)
지금부터는 동적 웹사이트의 본격적인 마우스, 키보드 이벤트에 대해 간단히 구현해보고자 한다.
selenium을 활용해 마우스 event를 동작해보고자 한다.
최근 간편로그인 등 로그인 과정에서 로그인 버튼을 누른 것에 대해 자동화가 필요한데, 이를 구현해보고자 한다.from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager # 주어진 웹사이트를 누른 후, 우리가 원하는 버튼 요소를 찾은 후 마우스 이벤트를 실행시켜봅시다. url = 'https://hashcode.co.kr/' driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver.get(url) driver.implicitly_wait(0.5) # 해당 class name 찾고 button = driver.find_element(By.CLASS_NAME, 'nav-link.nav-signin') # 버튼을 누르라고 명령 ActionChains(driver).click(button).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 import time # driver를 이용해 해당 사이트에 요청을 보내봅시다. driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver.get('https://hashcode.co.kr') time.sleep(1) # 내비게이션 바에서 "로그인" 버튼을 찾아 눌러봅시다. button = driver.find_element(By.CLASS_NAME, 'nav-link.nav-signin') ActionChains(driver).click(button).perform() time.sleep(1) # "아이디" input 요소에 여러분의 아이디를 입력합니다. id_input = driver.find_element(By.ID, 'user_email') ActionChains(driver).send_keys_to_element(id_input, '여러분의 아이디').perform() time.sleep(1) # "패스워드" input 요소에 여러분의 비밀번호를 입력합니다. pw_input = driver.find_element(By.ID, 'user_password') ActionChanins(driver).senf_keys_to_element(pw_input, '여러분의 패스워드').perform() time.sleep(1) # "로그인" 버튼을 눌러서 로그인을 완료합니다. button = driver.find_element(By.CLASS_NAME, 'btn-sign-in') ActionChains(driver).click(button).perform() time.sleep(1)
Interactive한 파이썬 코드 작성, 공유를 위한 개발 도구