차밍이

[Python] Selenium 의 두 가지 Wait 방법 - implicitly wait & explicitly wait 본문

파이썬/자동화

[Python] Selenium 의 두 가지 Wait 방법 - implicitly wait & explicitly wait

2022. 4. 22. 10:56
반응형

웹페이지가 완전히 로딩되지 않아서 문제가 발생하는 경우가 종종 있다.

예를들어 ElementNotVisibleException 에러가 발생한다.

웹페이지가 다 열리지 않은 상태에서 특정 객체를 찾으려고 하면, 해당 객체가 없어서 찾을 수 없다는 에러를 발생시키는 것이다.

이를 히결하려면 로딩이 완전히 될 때까지 기다려야 한다.

 

Selenium의 두 가지 Wait 방법

  • Implicitly wait: 정해진 시간만큼 충분히 기다리기
  • Explicitly wait: 어떤 조건이 만족할 때까지 기다리기

 

Implicitly wait

Implicitly wait을 10초로 설정하면 페이지가 로딩되는데 10초까지 기다립니다.

만약 페이지 로딩이 2초에 완료되었다면 더 기다리지 않고 다음 코드를 수행합니다.

기본 설정은 0초로 되어있고, 한번만 설정하면 driver를 사용하는 모든 코드에 적용된다.

아래 코드처럼 get을 호출하기 전에 wait 시간을 10초로 설정하면,

get이 페이지가 모두 로딩될 때까지 기다린 후 find_element_by_class로 element를 찾습니다.

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("https://chancoding.tistory.com/199")
myDynamicElement = driver.find_element_by_class_name("area_title")

 

Explicitly wait

Explicitly wait은 명시적으로 어떤 조건이 성립했을 때까지 기다립니다.

조건이 성립하지 않으면 timeout으로 설정된 시간만큼 최대한 기다립니다.

다음 코드는 ID가 someid인 element가 clickable이 될 때까지 기다리고, 그 element를 리턴하는 코드입니다. get() 코드 다음으로 wait.until() 코드를 추가하시면 됩니다. wait.until()은 특정 조건이 만족될 때까지 기다리고 그 element를 리턴합니다.

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

driver = webdriver.Chrome()
driver.get("https://chancoding.tistory.com/199")

# wait until someid is clickable
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

먼저 WebDriverWait 객체를 생성합니다. 인자로 driver와 timeout이 들어갑니다. 이 객체는 재사용할 수 있기 때문에 전역에 객체를 만들고 그 이후에 재사용하면 좋습니다.

조건을 설정하는 방법은 wait.until(조건)처럼 인자에 기다릴 조건을 넣으시면 됩니다.

위의 예제에서 조건에 해당하는 것은 아래 코드인데요. ID가 someid인 element가 clickable이 될 때까지 기다린다는 의미입니다.

EC.element_to_be_clickable((By.ID, 'someid')

아래 코드 처럼 By를 변경하여 class name이나 name으로 element를 찾게 할 수도 있습니다.

EC.element_to_be_clickable((By.CLASS_NAME, 'some_classname')
EC.element_to_be_clickable((By.NAME, 'some_name')

clickable이 싫다면 아래 처럼 element_to_be_clickable를 다른 조건으로 변경할 수도 있습니다.

EC.title_is(...)
EC.title_contains(...)
EC.presence_of_element_located(...)
EC.visibility_of_element_located(...)
EC.visibility_of(...)
EC.presence_of_all_elements_located(...)
EC.text_to_be_present_in_element(...)
EC.text_to_be_present_in_element_value(...)
EC.frame_to_be_available_and_switch_to_it(...)
EC.invisibility_of_element_located(...)
EC.element_to_be_clickable(...)
EC.staleness_of(...)
EC.element_to_be_selected(...)
EC.element_located_to_be_selected(...)
EC.element_selection_state_to_be(...)
EC.element_located_selection_state_to_be(...)
EC.alert_is_present(...)

모든 코드에 적용되는 implicitly wait과 다르게, explicitly wait은 코드를 넣은 위치에서만 기다립니다.

Reference

https://codechacha.com/ko/selenium-explicit-implicit-wait/

반응형

관련된 글 보기

Comments