1. Selenium
2. Wait and Call
3. 이벤트 처리
Selenium이란
Python을 이용해서 웹 브라우저를 조작할 수 있는 자동화 프레임워크
설치
# 셀레니움 설치
%pip install selenium
# 웹 브라우저를 제어할 수 있는 자동화 프레임 워크 : WebDriver
%pip install webdriver-manager
# selenium으로부터 webdriver 모듈을 불러옵니다.
from selenium import webdriver
# webdriver 안에 있는 chorme.service에 있는 Service 호출
# Chrome 객체 생성시 필요한 인자로 사용
from selenium.webdriver.chrome.service import Service
# webdriver_manager로 Chrome 버젼 연동
from webdriver_manager.chrome import ChromeDriverManager
# selenium을 사용하기 위해선 driver 객체를 만들어야함
# driver 객체는 특정 웹 브라우저에 종속되어 있음 ( 이 경우 Chrome )
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

# 만든 Chrome 브라우저에서 요청을 보냄
driver.get("http://www.example.com")
# 응답 받은 page_source : html 코드 확인
print(driver.page_source)

with-as
with-as구문을 통해 주어진 명령이 끝나면 driver를 종료하도록 설정 가능
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("http://www.example.com")
print(driver.page_source)
7일차에서
브라우저가 html코드를 parsing해서 DOM 모델로 만드는 것과
DOM Tree를 순회해서 특정 원소를 조회할 수 있다는 것도 배웠음따라서 selenium은 이미 브라우저를 활용하고 있기에,
받아온 응답으로부터 특정 요소를 추출할 수 있음을 알 수 있다.
# By를 import
from selenium.webdriver.common.by import By
# p 태그에 해당하는 요소 하나를 찾기
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("http://www.example.com")
print(driver.find_element(By.TAG_NAME,"p").text)
# p 태그에 해당하는 요소 여러개를 찾기
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("http://www.example.com")
# 다수이므로 list형태로 반환됨
for element in driver.find_elements(By.TAG_NAME,"p") :
print("Text:",element.text)
Driver의 요소 찾기 메소드
요소 하나 찾기
.find_element(by, target)
by : 대상을 찾는 기준 : ID, TAG_NAME, CLASS_NAME, ...
target : 대상의 속성
e.g.) driver.find_element(By.TAG_NAME,"p")
요소 여러 개 찾기
.find_elements(by, target)
by : 대상을 찾는 기준 : ID, TAG_NAME, CLASS_NAME, ...
target : 대상의 속성
e.g.) driver.find_elements(By.TAG_NAME,"p")
Implicit Wait / Explicit Wait
Selenium은 동적 웹 사이트에 대한 지원을 진행하기 위해 명시적 기다림(Explicit Wait) 과 암묵적 기다림(Implicit Wait) 을 지원
IndieStreet 이벤트 스크래핑
https://indistreet.com/live?sortOption=startDate%3AASC
( 관찰 결과 : 스크래핑 방지 목적으로 class 이름을 랜덤하게 생성하는 것을 확인 )
=> 위치를 활용한 스크래핑 진행
XPath
XML, HTML 문서등의 요소의 위치를 경로로 표현하는 것을 의미

첫 시도
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
# 위에서 복사한 XPath를 경로에 넣어줌
driver.find_element(By.XPATH,'//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]')
웹페이지가 동적웹페이지이기 때문에 갱신되어 오류 발생
Implicit Wait
# 주의사항 : 반드시 해당 시간을 기다리는 것이 아니라, 로딩이 다 될때까지의 한계 시간을 의미
# selenium의 WebDriverWait을 호출
from selenium.webdriver.support.ui import WebDriverWait
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
# 요청이 완벽하게 응답이 되면 다음 것을 실행
# 혹은 10초 간 기다림
# => 정리하면 일단 10초 간 기다리지만, 완벽한 응답이 왔다 싶으면 다음으로 넘어감
driver.implicitly_wait(10)
print(driver.find_element(By.XPATH,'//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]').text)
Explicit Wait
WebDriverWait()과 두 메서드를 활용해서 Explicit Wait을 적용할 수 있습니다.
until(): 인자의 조건이 만족될 때까지 until_not() 인자의 조건이 만족되지 않을 때까지 e.g.)
# id가 `target`인 요소가 존재할 때까지 10초 간 기다린 후 다음 명령을 진행
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "target")))
EC
EC.presence_of_element_located()
# Explicit Wait
from selenium.webdriver.support import expected_conditions as EC
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
# Explicit Wait
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH,'//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]')))
print(element.text)
# 10개의 이름 추출
from selenium.webdriver.support.ui import WebDriverWait
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver :
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.implicitly_wait(10)
for i in range(1,11) :
print(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)).text)
목표
해시코드 로그인 과정을 자동화하는 것
목표에 대한 의미
최근 서비스는 간편 로그인 기능을 제공하는 경우가 많음
간편 로그인 특성상,
특정 플랫폼에서 로그인을 요청하는 경우가 많다.
이를 편리하게 진행하기 위해선 Web Browser 상에서,
즉, Selenium 상에서 진행하는 것이 간편하다.
왜 굳이 Selenium 로그인까지 해야하나?
로그인을 해야 Scraping이 가능한 웹 사이트도 있기 때문.
Event
웹 페이지에서 일어나는 일들을 뜻함
Mouse Event
마우스 입력의 과정
find_element() 이용)click을 통해 전달.perform()을 통해 동작e.g.)
# id가 button인 요소를 호출
button = driver.find_element(By.ID, "button")
# ActionChain : Action에 Chain을 건다.
# 여러 Action을 연쇄적으로 수행할 수 있도록 하는 것
# 예를 들어, ctrl-c 같은 것을 가능하게 해주는 것
ActionChains(driver).click(button).perform()
로그인 버튼 누르기
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
# 웹 사이트 요청
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://hashcode.co.kr/")
driver.implicitly_wait(0.5)
# 로그인 버튼을 실행 시킴
button = driver.find_element(By.CLASS_NAME, "nav-link.nav-signin")
ActionChains(driver).click(button).perform()
Keyboard Event
키보드 입력 과정
find_element() 이용)send_keys_to_element를 통해 전달합니다..perform()을 통해 동작합니다.e.g.)
text_input = driver.find_element(By.ID, "textInput")
ActionChains(driver).send_keys_to_element(text_input, "abc").perform()
로그인 창에서 ID, PW 입력하고 로그인하기
# driver를 이용해 해당 사이트에 요청을 보내봅시다.
import time
# 웹 사이트 접속
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://hashcode.co.kr/")
time.sleep(1)
# 메뉴를 실행 시킴
button = driver.find_element(By.XPATH, '//*[@id="main-app-header"]/header/section/div/div/button')
ActionChains(driver).click(button).perform()
time.sleep(1)
# 로그인 버튼을 실행 시킴
button = driver.find_element(By.XPATH, '//*[@id="main-app-header"]/header/div[5]/div/section/div[1]/a[2]')
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")
ActionChains(driver).send_keys_to_element(pw_input, "password").perform()
time.sleep(1)
# "로그인" 버튼을 눌러서 로그인을 완료합니다.
button = driver.find_element(By.ID,"btn-sign-in")
ActionChains(driver).click(button).perform()