크롤링을 하거나 테스팅을 할 때 웹이 로드되길 기다려야 할 때가 있습니다.

관련 개념을 간략하게 살펴보고 Selenium에서는 어떤 기능을 제공하는지 간단하게 알아봅시다.

 

AJAX

요즘의 웹앱들은 AJAX 테크닉을 이용해서 구동되는 경우가 많습니다.
AJAX 테크닉이란 JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 XML 데이터를 주고받는 기술을 의미합니다.
AJAX를 이용하면 브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부 데이터만을 로드할 수 있습니다.

페이지 리로드의 경우 전체 리소스를 다시 불러와야하는데 이미지, 스크립트 , 기타 코드등을 모두 재요청할 경우 불필요한 리소스 낭비가 발생하게 됩니다. 그러나 비동기식 방식을 이용할 경우 필요한 부분만 불러와 사용할 수 있으므로 성능에 매우 큰 장점이 있습니다.

AJAX의 진행과정

AJAX의 진행과정은 다음과 같습니다.

  1. XMLHttpRequest Object를 만든다.
    • request를 보낼 준비를 브라우저에게 시키는 과정
    • 이것을 위해서 필요한 method를 갖춘 object가 필요함
  2. callback 함수를 만든다.
    • 서버에서 response가 왔을 때 실행시키는 함수
    • HTML 페이지를 업데이트 함
  3. Open a request
    • 서버에서 response가 왔을 때 실행시키는 함수
    • HTML 페이지를 업데이트 함
  4. send the request

Selenium에서 대기 과정이 필요한 이유

다만 XMLHttpRequest를 통해 통신하는 경우, 사용자에게 아무런 진행 정보가 주어지지 않는다는 단점이 있습니다. 또한, 브라우저에서 페이지를 로드하면 해당 페이지 내의 요소가 다른 시간 간격으로 로드 될 수 있으므로 요소가 아직 DOM에 없으면 코드는 ElementNotVisibleException을 발생시킬 수 있습니다.

따라서 Selenium은 wait을 사용해 이 문제를 해결하고자 했습니다.
Selenium에서는 두 가지 타입의 wait method를 제공합니다.
하나는 Explicit Waits이고, 나머지 하나는 Implicit Waits 입니다.

Explicit Waits

특정 상태가 될때까지 기다리고, 특정 상태가 되면 바로 실행합니다.
다음은 Selenium docs에서 제공하는 코드입니다.

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()

위 코드에서 Selenium은 주어진 기준과 일치하는 요소를 찾을 때까지 최대 10초 동안 기다립니다. 해당 시간에 요소가 발견되지 않으면 TimeoutException이 발생합니다.

Implicit Waits

WebDriver가 즉시 사용할 수 없는 요소를 찾으려고 할 때 일정 시간동안 DOM을 기다리도록(polling) 지시합니다. 기본 설정은 0 입니다.

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

 

 

참고 문헌

AJAX

  • https://velog.io/@surim014/AJAX%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

태그:

카테고리:

업데이트:

댓글남기기