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.Firefox()
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()
공식 홈페이지에 올라와 있는 예제이다. 한 번 살펴보자
WebDriverWait(driver, 10)
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
객체를 생성한다.
driver
: 사용할 webdriver 객체를 전달한다timeout
: 최대로 대기할 시간이며 단위는 초이다poll_frequency
: 로딩이 완료될때까지 기다리는 동안 기다리는 element를 일정 시간 간격마다 호출해보게 되는데, 이때 얼마만큼의 시간 간격마다 호출할 것인지를 결정한다. 기본 값은 0.5초이다ignored_exceptions
: 일정 간격마다 element를 호출하는동안 발생하는 Exception 중 무시할 것을 지정할 수 있다. 기본값으로는 NoSuchElementException만 무시한다. iterable한 형식으로 무시할 Exception들을 전달해주면 된다. .until(...)
WebDriverWait객체에는 두 가지 메소드가 있다.
until(method, message='')
: method를 실행해서 False가 아닐 때 까지 기다리게 된다. 공식 API 페이지에 예제가 나와있다. until(lambda x: x.find_element_by_id(“someId”))
람다식을 사용하여 *someId* 라는 id를 가진 element를 찾아 False가 아닌 값을 반환할 때 까지 기다리게 된다.
until_not(method, message='')
: method를 실행해서 Return값이 **False
가 나오지 않을 때 까지** 기다리게 된다. 역시 공식 API 페이지에 예제가 나와있다.
until_not(lambda x: x.find_element_by_id(“someId”).is_displayed())
find_element_by_id(“someId”).is_displayed()
가 **False
가 될때 까지,** 기다리게 된다. False값을 받아야 하기에 False
값을 반환하는 is_displayed()
와 같은 메소드를 사용해야 한다.
둘 다 message인자를 통해 error message를 custom 할 수 있다.
until(
expected_conditions.element_to_be_clickable(click),
message='My custom message.',
)
>>> selenium.common.exceptions.TimeoutException: Message: My custom message.
Selenium은 until과 until_not에 condition으로 사용할 method중 빈번하게 쓰이는 것들을 미리 정의하여 제공하고 있다.
from selenium.webdriver.support import expected_conditions as EC
expected_conditions 모듈을 import하여 사용할 수 있으며 그 목록은 다음과 같다
title_is
title_contains
presence_of_element_located
visibility_of_element_located
visibility_of
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
element_to_be_clickable
staleness_of
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present
HTML내에서 어떤 Attribute를 가지고 element를 찾을것인지 정의할 때 사용 할 수 있다
예를들어 아래 두 줄의 코드는 둘 다 같은 결과를 반환한다
driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_element_by_xpath('//button[text()="Some text"]')
By 모듈을 import하여 사용할 수 있으며, 정의된 locator들은 다음과 같다
from selenium.webdriver.common import By
CLASS_NAME
= 'class name'
CSS_SELECTOR
= 'css selector'
ID
= 'id'
LINK_TEXT
= 'link text'
NAME
= 'name'
PARTIAL_LINK_TEXT
= 'partial link text'
TAG_NAME
= 'tag name'
XPATH
= 'xpath'
이제 위의 예제를 다시 확인해보자
EC.presence_of_element_located((By.ID, "myDynamicElement"))
목록에 따르면 presence_of_element_located
는 element가 DOM에 존재하는지 확인한다. 주의할점은 이는 꼭 브라우저 상에 element가 보이지 않아도 DOM상에 존재 하기만 하면 해당 WebElement객체를 return한다
위 코드는 id attribute의 값이 "myDynamicElement"인 element를 찾아서, 해당 element가 DOM상에 있는것이 확인하게 된다
Selenium의 Explicit Wait에서는 특정한 attribute의 값과 특정한 Condition을 조합하여 여러가지 상황에 대응할 수 있다. 잘 조합하여 유용하게 써 보자