복붙노트

[PYTHON] Selenium WebDriver for Python이 페이지가로드 될 때까지 기다리십시오.

PYTHON

Selenium WebDriver for Python이 페이지가로드 될 때까지 기다리십시오.

무한한 스크롤에 의해 구현 된 페이지의 모든 데이터를 긁어 내고 싶습니다. 다음 python 코드가 작동합니다.

for i in range(100):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(5)

즉, 아래로 스크롤 할 때마다 5 초 정도 기다려야합니다. 일반적으로 페이지에서 새로 생성 된 콘텐츠를로드하기에 충분합니다. 그러나 이것은 시간이 효율적이지 않을 수 있습니다. 페이지가 5 초 이내에 새 내용로드를 완료 할 수 있습니다. 아래로 스크롤 할 때마다 페이지가 새 내용로드를 완료했는지 어떻게 알 수 있습니까? 이 문제를 발견 할 수 있으면 페이지가로드되는 것을 알게되면 다시 스크롤하여 내용을 볼 수 있습니다. 이것은보다 효율적입니다.

해결법

  1. ==============================

    1.webdriver는 기본적으로 .get () 메소드를 통해 페이지가로드 될 때까지 대기합니다.

    webdriver는 기본적으로 .get () 메소드를 통해 페이지가로드 될 때까지 대기합니다.

    @ user227215가 말한 것처럼 특정 요소를 찾고있을 수 있으므로 WebDriverWait을 사용하여 페이지에있는 요소를 기다려야합니다.

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.common.exceptions import TimeoutException
    
    browser = webdriver.Firefox()
    browser.get("url")
    delay = 3 # seconds
    try:
        myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'IdOfMyElement')))
        print "Page is ready!"
    except TimeoutException:
        print "Loading took too much time!"
    

    나는 그것을 점검하는 데 사용했다. 다른 유형의 메소드를 사용하여 위치 지정자를 찾을 수 있습니다.

    편집 1 :

    나는 webdriver가 기본적으로 페이지가로드 될 때까지 기다릴 것이라고 언급해야한다. 프레임이나 Ajax 요청을로드 할 때까지 기다리지 않습니다. 이것은 .get ( 'url')을 사용할 때 브라우저가 페이지가 완전히로드 될 때까지 기다린 다음 코드의 다음 명령으로 이동한다는 의미입니다. 그러나 Ajax 요청을 게시 할 때 webdriver는 기다리지 않고 페이지 또는 페이지 일부가로드 될 때까지 적절한 시간 동안 기다리는 것은 사용자의 책임입니다. 따라서 expected_conditions라는 모듈이 있습니다.

  2. ==============================

    2.presence_of_element_located에 대한 find_element_by_id를 생성자에 전달하려고하면 (허용 된 대답에 표시된대로) NoSuchElementException이 발생합니다. 나는 fragles의 주석에 구문을 사용해야 만했다.

    presence_of_element_located에 대한 find_element_by_id를 생성자에 전달하려고하면 (허용 된 대답에 표시된대로) NoSuchElementException이 발생합니다. 나는 fragles의 주석에 구문을 사용해야 만했다.

    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Firefox()
    driver.get('url')
    timeout = 5
    try:
        element_present = EC.presence_of_element_located((By.ID, 'element_id'))
        WebDriverWait(driver, timeout).until(element_present)
    except TimeoutException:
        print "Timed out waiting for page to load"
    

    이것은 문서의 예제와 일치합니다. 여기에 By의 설명서 링크가 있습니다.

  3. ==============================

    3.아래 3 가지 방법을 찾으십시오.

    아래 3 가지 방법을 찾으십시오.

    확인 페이지 readyState (신뢰할 수 없음) :

    def page_has_loaded(self):
        self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))
        page_state = self.driver.execute_script('return document.readyState;')
        return page_state == 'complete'
    

    새 페이지 ID와 이전 페이지 ID 비교 :

    def page_has_loaded_id(self):
        self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))
        try:
            new_page = browser.find_element_by_tag_name('html')
            return new_page.id != old_page.id
        except NoSuchElementException:
            return False
    

    staleness_of 메소드 사용 :

    @contextlib.contextmanager
    def wait_for_page_load(self, timeout=10):
        self.log.debug("Waiting for page to load at {}.".format(self.driver.current_url))
        old_page = self.find_element_by_tag_name('html')
        yield
        WebDriverWait(self, timeout).until(staleness_of(old_page))
    

    자세한 내용은 해리의 블로그를 확인하십시오.

  4. ==============================

    4.selenium / webdriver / support / wait.py에서

    selenium / webdriver / support / wait.py에서

    driver = ...
    from selenium.webdriver.support.wait import WebDriverWait
    element = WebDriverWait(driver, 10).until(
        lambda x: x.find_element_by_id("someId"))
    
  5. ==============================

    5.David Cullen의 답변에서 언급했듯이 다음과 같은 줄을 사용하는 것이 좋습니다.

    David Cullen의 답변에서 언급했듯이 다음과 같은 줄을 사용하는 것이 좋습니다.

    element_present = EC.presence_of_element_located((By.ID, 'element_id'))
        WebDriverWait(driver, timeout).until(element_present)
    

    By 구문과 함께 사용할 수있는 가능한 모든 위치 지정자를 어디서든지 찾기가 어려웠으므로 여기에 목록을 제공하는 것이 유용 할 것이라고 생각했습니다. Ryan Mitchell의 Web Scraping with Python에 따르면 :

  6. ==============================

    6.100 번 아래로 스크롤하는 대신 DOM에 더 이상 수정이 없는지 확인할 수 있습니다 (페이지의 맨 아래에 AJAX가 느리게로드되는 경우)

    100 번 아래로 스크롤하는 대신 DOM에 더 이상 수정이 없는지 확인할 수 있습니다 (페이지의 맨 아래에 AJAX가 느리게로드되는 경우)

    def scrollDown(driver, value):
        driver.execute_script("window.scrollBy(0,"+str(value)+")")
    
    # Scroll down the page
    def scrollDownAllTheWay(driver):
        old_page = driver.page_source
        while True:
            logging.debug("Scrolling loop")
            for i in range(2):
                scrollDown(driver, 500)
                time.sleep(2)
            new_page = driver.page_source
            if new_page != old_page:
                old_page = new_page
            else:
                break
        return True
    
  7. ==============================

    7.어떻게 WebDriverWait을 While 루프에 넣고 예외를 잡는가?

    어떻게 WebDriverWait을 While 루프에 넣고 예외를 잡는가?

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.common.exceptions import TimeoutException
    
    browser = webdriver.Firefox()
    browser.get("url")
    delay = 3 # seconds
    while True:
        try:
            WebDriverWait(browser, delay).until(EC.presence_of_element_located(browser.find_element_by_id('IdOfMyElement')))
            print "Page is ready!"
            break # it will break from the loop once the specific element will be present. 
        except TimeoutException:
            print "Loading took too much time!-Try again"
    
  8. ==============================

    8.당신은 driver.implicitly_wait을 시도해 보셨습니까? 그것은 드라이버의 설정과 같아서 세션에서 한 번만 호출하면 기본적으로 드라이버에게 각 명령을 실행할 수있을 때까지 주어진 시간 동안 대기하도록 지시합니다.

    당신은 driver.implicitly_wait을 시도해 보셨습니까? 그것은 드라이버의 설정과 같아서 세션에서 한 번만 호출하면 기본적으로 드라이버에게 각 명령을 실행할 수있을 때까지 주어진 시간 동안 대기하도록 지시합니다.

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

    따라서 대기 시간을 10 초로 설정하면 가능한 한 빨리 명령을 실행하고 포기하기 10 초를 기다립니다. 비슷한 스크롤 - 다운 시나리오에서 이것을 사용했기 때문에 왜 당신의 경우에는 효과가 없을지 모르겠습니다. 희망이 도움이 :)

  9. from https://stackoverflow.com/questions/26566799/wait-until-page-is-loaded-with-selenium-webdriver-for-python by cc-by-sa and MIT license