데이터 분석/크롤링

[AI개발자 부트캠프 Elice] Selenium심화, 브라우저 제어

temporubato108 2024. 11. 24. 18:03

1. 브라우저 제어

Q. 브라우저 제어는 왜 해야할까요?

  1. 로그인 자동화
    • 로그인 후에만 나오는 웹 페이지 분석을 위해
    • ID와 비밀번호 입력 후 로그인 버튼 클릭 (또는 엔터키 입력)
  2. 드랍다운 버튼 클릭
    • 드랍다운 버튼을 클릭해야만 나오는 요소의 추출을 위해
    • 드랍다운 버튼을 찾아서 클릭

→ 답은 Selenium입니다!!

 


 

2. 브라우저 로딩 기다리기

브라우저 로딩이 지연되는 경우가 있습니다.


이럴 때는 어떻게 해야할까요?

Point I
time.sleep(n): 무조건 기다리기

import time

with webdriver.Firefox() as driver:
    driver.get(url) #  웹페이지 로딩
    time.sleep(10) # 10초간 기다리기
    
    e = driver.find_element()
    ...
  • python 내장 라이브러리
  • n초만큼 무조건 기다림
  • 내가 원하는 요소가 불러와 졌어도 주어진 시간을 계속 기다림

Point II
implicitly_wait(n): 암시적 기다리기

with webdriver.Firefox() as driver:
    driver.implicitly_wait(10)
    driver.get(url) # 웹 페이지 로딩
    
    e = driver.find_element()
    ...
  • 암시적으로 기다림 수행
  • 앞으로 요소를 추출할 때 (find_element) 최대 n초까지 기다림
  • 해당 요소의 로딩이 끝나면 즉시 기다리기를 종료하고 코드를 수행
  • 한 번 설정해주면 해당 브라우저에서 계속해서 적용

Point III
presence_of_element_located: 명시적 기다리기

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

with webdriver.Firefox() as driver:
    driver.implicitly_wait(10)
    driver.get(url) # 웹 페이지 로딩
    
    e = WebDriverWait(driver, 30).until(
        EC.presence_of_element_located((By.ID, "id_name"))
        # 괄호 안의 요소가 나타날 때까지 기다림
    ) # 해당 요소를 불러올 때까지 30초 기다림
    ...
  • 명시된 요소가 해당 방식으로 불러와질 때까지 최대 n초 기다림
  • 요소는 class_name, xpath 등 다양한 방법으로 찾을 수 있음

다른 예시)

  • element_to_be_clickable: 해당 요소가 클릭 가능해질 때까지 기다림

 


 

3. 키보드/마우스 입력

Point I
키보드 입력

from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

# id 입력
driver \
    .find_element(By.XPATH,'//*[@id="id"]') \
    .send_keys('my_id')

# password 입력 + 엔터
driver \
    .find_element(By.XPATH,'//*[@id="pw"]') \
    .send_keys('my_password' + Keys.ENTER)
  • send_keys: 해당 요소에 나열된 key sequence를 순차적으로 입력
  • Keys: 특수 키를 쓸 수 있게 해주는 class로 ENTER, CONTROL, SHIFT 등 모든 특수키가 있으며 항상 대문자로 작성

Point II
마우스 입력

# 로그인 버튼 클릭
driver \
    .find_element(By.XPATH,'//*[@id="log.login"]') \
    .click()
  • click: 해당 요소를 클릭하는 효과

 


 

4. 다양한 입력, Action Chains

Point I

  • 기본 입력의 한계: 각 요소에 key sequence를 입력하거나 마우스 클릭 등의 액션을 할 수 있지만, 더 이상의 복잡한 액션을 할 수 없습니다.
  • Action Chains: 여러 가지의 action을 chain처럼 엮어 수행하는 기능으로 이를 통해 좀 더 복잡한 액션을 할 수 있습니다.

Point II

Point III
ActionChains의 키보드 입력

# 요소 찾기
_id = driver.find_element(By.XPATH,'//*[@id="id"]')
_pw = driver.find_element(By.XPATH,'//*[@id="pw"]')

# 액션 수행
webdriver.ActionChains(driver) \
    .send_keys_to_element(_id, 'my_id') \
    .send_keys_to_element(_pw, 'my_pw') \
    .send_keys(Keys.ENTER) \
    .perform()
  • send_keys_to_element: 주어진 요소에 주어진 key sequence를 입력하여 하나의 ActionChains 내에서 여러 요소에 액션을 수행
  • send_keys: 요소가 주어지지 않기 때문에 현재 커서가 위치한 곳에서 key sequence를 입력

Point IV
ActionChains의 다양한 method 조합

# 컨트롤 + click
_button = driver.find_element(By.XPATH,'//button')
chains = webdriver.ActionChains(driver)

chains.key_down(Keys.CONTROL) # 컨트롤 버튼 누른 채로
chains.click(_button) # 버튼 요소 클릭
chains.perform()

 

# 마우스 커서를 올렸다, 3초 뒤에 떼기
_button = driver.find_element(By.XPATH'//button')
chains = webdriver.ActionChains(driver)

chains.move_to_element(_button) \
    .pause(3) \
    .move_by_offset(100, 100) \
    .perform()
  • move_to_element: 주어진 요소로 마우스 커서를 이동
  • pause: n초만큼 멈췄다 뒤의 액션을 수행
  • move_by_offset: x, y축으로 주어진 수치만큼 이동