Selenium의 Waits

I'm Cape·2023년 6월 2일
0

제로베이스 데이터 취업 스쿨 5주차 스터디노트 6호

왜 알아서 기다리지 못하니?

Selenium 사용 시 최초로 마주치는 고비는
웹페이지와 코드가 동기화되지 않는다는 것이다.

예를 들어, id가 "hello_world"인 element를 찾는데,
브라우저에서는 로딩이 되지 않은 경우이다.

"알아서 element가 로딩될 때까지 기다려주면 안되겠니?"

Selenium의 입장을 들어보자.
"아니 element가 있는지 없는지 확실하지도 않은데 언제까지 기다려요"

음. 납득되는 항변이다.
그러면 우리는 Selenium에게 더 구체적으로 이야기를 해주어야 한다.

뭘 찾든 그냥 5초 기다려

Implicit Waits이다.

공식문서의 설명을 읽어보자.
By implicitly waiting, WebDriver polls the DOM for a certain duration when trying to find any element.

두가지 키워드가 있다. poll과 any이다.
(공식문서에서는 any만 강조처리 되어있다)

  1. poll
    poll...? 투표한다고?
    polling은 컴퓨터 공학 용어이다.
    위키피디아에서 함께 정의를 알아보자.

Polling is the process where the computer or controlling device waits for an external device to check for its readiness or state, often with low-level hardware.

대충 예시 & 요약하자면 프린터를 사용하기 위해서 컴퓨터가 프린터의 연결이 확인될 때까지 대기할 때, 여기서 외부 장비의 준비를 기다린다는 것이 polling이다.

브라우저와 Selenium은 두가지 다 하드웨어는 아니지만, 어쨌거나 Selenium이 브라우저가 준비되기를 기다리는 것이다.

  1. any
    Selenium으로 브라우저 조작을 하려면,
    element를 찾는 것이 필수적이다.
    Implicit Waits를 사용하면,
    어떤 element를 찾든지 제시된 timeout만큼 selenium이 기다리는 것이다.

다음과 같이 사용한다.

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10)

driver.get("https://www.opinet.co.kr/searRgSelect.do")
urban = driver.find_element(By.ID, "SIDO_NM0") # 10 기다림
sub_urban = driver.find_element(By.ID, "SIGUNGU_NM0") # 역시 10 기다림

참고로, Implicit Waits는 사용한다면 단 한번만 사용하면 된다.
사용하고 있는 driver의 attribute를 변경하는 것이다.

Once set, the implicit wait is set for the life of the session.
따라서, attribute를 변경한 driver을 사용하는 동안 계속 적용된다.
(기다리는 시간이 milisec인지 그냥 sec인지 잘 모르겠다.)

ID가 glopopd_excel인 element가 클릭 가능할 때까지 3초 기다려

Explicit Waits이다.
확실한 조건을 제시한다는 점이 Implicit Waits와 다르다.

Selenium이 이전에 이렇게 항변했다.
"아니 element가 있는지 없는지 확실하지도 않은데 언제까지 기다려요"

그러니 우리는 Explicit Waits를 사용하여 Selenium에게 언제까지 기다릴지 알려주는 것이다.
"ID가 glopopd_excel인 element가 클릭 가능할 때까지 3초 기다리고, 없으면 에러 발생시켜."

다음과 같이 사용한다.

from selenium import webdriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By

driver.get("https://www.opinet.co.kr/searRgSelect.do")

# expected_conditions를 활용한 Explicit Waits
availability = expected_conditions.element_to_be_clickable(By.ID, "glopopd_excel")
WebDriverWait(driver, timeout=3).until(availability)

sub_urban = driver.find_element(By.ID, "SIGUNGU_NM0") # 이건 3초 기다리지 않음

절대 함께 사용하지 마세요!

공식문서에서 2번이나 강조하는 내용이다.

  • Mixing explicit waits and implicit waits will cause unintended consequences, ...
  • Warning: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. ...
profile
Impact

0개의 댓글