DevCourse TIL Day4 Week3

김태준·2023년 4월 20일
0

Data Enginnering DevCourse

목록 보기
10/93
post-thumbnail

이전 학습으로 동적 웹사이트는 브라우저의 자동화가 필요함을 알게 되었고 이를 해결하고자 파이썬 라이브러리인 Selenium에 대해 간단히 알아보았다.

오늘은 selenium을 직접 구현해보면서 작동 방식에 대해 알아보고자 한다.

✍️ Web browser 연동

웹 브라우저와의 연동을 위해 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)

✅ Wait & Call

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)

✍️ Exercise 1 - 여러 요소 이벤트 제목 출력하기

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)

✅ Jupyterlab

Interactive한 파이썬 코드 작성, 공유를 위한 개발 도구

profile
To be a DataScientist

0개의 댓글