web-dev-qa-db-fra.com

Faites défiler vers le bas de la page infinie avec PhantomJS dans Python

J'ai réussi à obtenir Python avec Selenium et PhantomJS pour recharger une page de défilement infinie à chargement dynamique, comme dans l'exemple ci-dessous. Mais comment cela pourrait-il être modifié de sorte qu'au lieu de définir un certain nombre de rechargements manuellement , le programme s'est arrêté en atteignant le fond du rocher?

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

Vous pouvez vérifier si le défilement a fait quelque chose à chaque étape.

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

Cela utilise un temps d'attente statique qui est mauvais car vous ne voulez pas attendre inutile quand il se termine plus vite et vous ne voulez pas que le script se ferme prématurément lorsque la charge dynamique est trop lente pour une raison quelconque.

Puisqu'une page charge généralement quelques éléments supplémentaires dans une liste, vous pouvez vérifier la longueur de la liste avant le chargement et attendre que l'élément suivant soit chargé.

Pour Twitter, cela pourrait ressembler à ceci:

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

J'ai utilisé une expression XPath, car PhantomJS 1.x a parfois un bogue lors de l'utilisation des sélecteurs CSS :nth-child().

version complète pour référence.

30
Artjom B.