셀레니움을 사용하다 보면 페이지 로딩 시간 또는 동적 페이지로 인해 요소가 불러와질 때까지 기다려야 하는 상황이 발생한다.
만약 요소가 없을 때 요소를 찾으려는 함수가 호출되면 ElementNotVisibleException이 발생하기 때문에 꼭 요소가 나타날 때까지 기다렸다가 진행해 주어야 한다.
사실 파이썬이나 셀레니움을 사용하는 경우가 별로 없어서 그전까지 대기가 필요하면 그냥 Python의 sleep()을 사용하였다.
from time import sleep
sleep(1) # 1초 대기
sleep(0.5) # 0.5초 대기
Python의 sleep 같은 경우에는 인수로 ms 단위가 아닌 초(sec) 단위의 숫자를 받기 때문에 사용하기에 매우 직관적이다.
그렇기 때문에 간단한 대기나 짧은 시간의 대기 정도는 sleep()을 사용해서 대기를 하는 것도 좋다.
하지만 sleep()을 사용하게 되면, 네트워크 상황이나 사양에 따라서 더 늦게 불러와질 수도 있고, 더 빨리 요소가 불러와질 경우에는 시간이 낭비되게 된다.
그래서 sleep()으로 대기하는 것이 아닌 셀레니움에서 제공하는 대기를 정리하기로 하였다.
1. 암시적 대기 (Implicit Waits)
우선 암시적 대기의 경우에는 driver에 설정을 해줄 수 있다.
sleep()과 마찬가지로 인수로는 초(sec) 단위를 사용한다. 기본 설정으로는 0초로 설정되어있는데
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 암시적 대기 시간 10초 설정
driver.get("https://mebadong.tistory.com")
위 코드와 같이 implicitly_wait()를 사용하여 암시적 대기 시간을 지정해줄 수 있다.
암시적 대기란 페이지가 로드될 때까지 기다리라는 뜻이다.
sleep()과 차이점은 sleep()은 지정된 시간 동안 무조건 기다리라는 뜻이고, 암시적 대기는 지정한 시간이 되기 전에 페이지 로드가 끝나면 다음 작업을 진행하라는 뜻이다.
만약 지정된 시간이 지나도 페이지가 로드되지 않으면 다음 작업을 실행하기 때문에 충분한 시간을 설정해 주어야 한다.
요즘은 웹에 문제가 있지 않은 이상 10초 정도로 설정하면 문제가 발생할 일은 거의 없을 것이다.
2. 명시적 대기 (Explicit Waits)
암시적 대기를 설정해도 문제가 생길 수 있는 부분이 있는데, 동적 페이지 같은 경우가 그렇다.
페이지는 로드가 되었지만 요소는 아직 전체가 불러와진 것이 아니기 때문에 암시적 대기를 걸어줘도 요소를 찾을 수 없는 경우가 생긴다.
명시적 대기 같은 경우에는 해당 요소가 불러와질 때까지 대기 상태를 걸어 명시적으로 기다리는 것이다.
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("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
위 코드는 myDynamicElement라는 ID를 가진 요소를 찾을 때까지 최대 10초 동안 기다린다.
10초 동안 TimeoutException이 발생하면서 500ms마다 ExpectedCondition을 호출하게 된다, 만약 10초가 지난 후에도 요소를 찾을 수 없을 경우 실패를 반환한다.
해당 요소를 찾게 되면 해당 요소를 반환하게 된다.
기본적으로 셀레니움에서 제공되는 expected condition은 다음과 같다.
- title_is
-> 페이지의 title이 일치하면 True, 그렇지 않으면 False를 반환한다. - title_contains
-> 페이지의 title에 대소문자를 구분하여 해당 문자열이 포함되어 있는지 확인한다. 포함되면 True, 그렇지 않으면 False를 반환한다. - presence_of_element_located
-> 페이지의 DOM에 요소가 있는지 확인한다. - visibility_of_element_located
-> 요소가 페이지의 DOM에 있고 볼 수 있는 상태인지 확인한다. 볼 수 있다는 상태는 요소가 표시될 뿐만 아니라 높이와 너비가 0보다 커야 한다. - visibility_of
-> 페이지의 DOM에 있는 요소가 보이는지 확인한다. - presence_of_all_elements_located
-> 페이지에 적어도 하나의 요소가 있는지 확인한다. - text_to_be_present_in_element
-> 주어진 텍스트가 지정된 요소에 있는지 확인한다. - text_to_be_present_in_element_value
-> 주어진 텍스트가 지정된 요소의 로케이터에 있는지 확인한다. - frame_to_be_available_and_switch_to_it
-> 주어진 프레임을 전환할 수 있는지 확인한다. - invisibility_of_element_located
-> 페이지의 DOM에 요소가 보이지 않거나 존재하지 않는지 확인한다. - element_to_be_clickable
-> 요소가 표시되고 클릭할 수 있는지 확인한다. - staleness_of
-> 요소가 더이상 DOM에 연결되지 않을 때까지 기다린다. 요소가 DOM에 연결이 되어있으면 False를 반환하고, 그렇지 않으면 True를 반환한다. - element_to_be_selected
-> 요소가 선택될 수 있는지 확인한다. - element_located_to_be_selected
-> 요소가 선택될 수 있는 위치에 있는지 확인한다. - element_selection_state_to_be
-> 지정된 요소가 선택되었는지 확인한다. - element_located_selection_state_to_be
-> 요소를 찾고, 요소가 선택된 상태인지 확인한다. - alert_is_present
-> 알림이 있는지 확인한다.
명시적 대기를 사용하고 싶어 정리한 포스팅인데 expected condition 부분은 그냥 번역기를 돌린 수준이라 시간이 날 때 하나씩 확인해 보면서 어떤 상태인지 확인할 필요가 있을 것 같다.
'Python' 카테고리의 다른 글
[Python] Python 반복문 개선하기 (0) | 2021.11.16 |
---|---|
[Python] Python 코드 실행시간 측정하기 (0) | 2021.11.12 |
[Selenium] Selenium Expected Condition 정리 (2) | 2021.10.30 |
[Python] 문자열 내에 리스트(배열) 안에 있는 문자가 포함되어있는지 검사하기 (0) | 2021.08.30 |
[Python] 파이썬으로 개발 문서를 만들어보자! Sphinx! (0) | 2021.07.30 |