Прокрутите вниз до бесконечной страницы с помощью PhantomJS в Python

Мне удалось заставить Python с Selenium и PhantomJS перезагрузить динамически загружаемую бесконечную страницу прокрутки, как в приведенном ниже примере. Но как это можно изменить, чтобы вместо того, чтобы вручную устанавливать несколько перезагрузок, программа остановилась при достижении дна капота?

reloads = 100000 #set the number of times to reload
pause = 0 #initial time interval between reloads
driver = webdriver.PhantomJS()

# Load Twitter page and click to view all results
driver.get(url)
driver.find_element_by_link_text("All").click()

# Keep reloading and pausing to reach the bottom
for _ in range(reloads):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(pause)

text_file.write(driver.page_source.encode("utf-8"))
text_file.close()

Ответ 1

Вы можете проверить, что прокрутка сделала что-либо на каждом шагу.

lastHeight = driver.execute_script("return document.body.scrollHeight")
while True:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(pause)
    newHeight = driver.execute_script("return document.body.scrollHeight")
    if newHeight == lastHeight:
        break
    lastHeight = newHeight

Это использует статическую сумму ожидания, которая является плохим, потому что вы не хотите ждать лишнего, когда она заканчивается быстрее, и вы не хотите, чтобы script выходил раньше, когда динамическая нагрузка слишком медленно по какой-то причине.

Так как на странице обычно загружается еще несколько элементов в список, вы можете проверить длину списка перед загрузкой и дождаться загрузки следующего элемента.

В твиттере это может выглядеть так:

while True:
    elemsCount = browser.execute_script("return document.querySelectorAll('.stream-items > li.stream-item').length")

    browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    try:
        WebDriverWait(browser, 20).until(
            lambda x: x.find_element_by_xpath(
                "//*[contains(@class,'stream-items')]/li[contains(@class,'stream-item')]["+str(elemsCount+1)+"]"))
    except:
        break

Я использовал выражение XPath, потому что у PhantomJS 1.x иногда возникает ошибка при использовании селекторов :nth-child() CSS.

Полная версия для справки.

Ответ 2

Просто небольшое улучшение, насколько я знаю.

Страница должна постоянно прокручиваться не с 0 позиции, а с предыдущей последней.

        new_height = 0 # initial value, before first loading of page
        last_height = self.driver.execute_script('return document.body.scrollHeight')

        while True:
            self.driver.execute_script('window.scrollTo({0}, {1});'.format(new_height, last_height))
            time.sleep(2) # seconds to wait
            new_height = self.driver.execute_script('return document.body.scrollHeight')

            if new_height == last_height:
                break
            last_height = new_height

PS Не хватает репутации, чтобы добавить комментарий к предыдущему ответу, сделанному Artjom B.