Comment puis-je faire défiler une page Web à l'aide de sélénium Webdriver en python?

132

J'utilise actuellement sélénium webdriver pour analyser la page d'amis de Facebook et extraire tous les identifiants du script AJAX. Mais j'ai besoin de faire défiler vers le bas pour obtenir tous les amis. Comment puis-je faire défiler vers le bas dans Selenium. J'utilise python.

user2523364
la source
driver.execute_script (f "window.scrollTo (0, {2 ** 127});")
AturSams

Réponses:

264

Vous pouvez utiliser

driver.execute_script("window.scrollTo(0, Y)") 

où Y est la hauteur (sur un moniteur fullhd, c'est 1080). (Merci à @lukeis)

Vous pouvez aussi utiliser

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

pour faire défiler vers le bas de la page.

Si vous voulez faire défiler jusqu'à une page avec un chargement infini , comme celles des réseaux sociaux, Facebook etc. (merci à @Cuong Tran)

SCROLL_PAUSE_TIME = 0.5

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

une autre méthode (grâce à Juanse) est, sélectionnez un objet et

label.sendKeys(Keys.PAGE_DOWN);
OWADVL
la source
1
Excellent, pouvez-vous expliquer un peu scrollHeight, qu'est-ce que cela signifie et comment ça marche en général?
Jason Goal
Comment utiliseriez-vous alors la variable "last_height"? J'ai quelque chose de similaire dans mon code et le navigateur fait défiler vers le bas. Cependant, lorsque je regarde les données que je racle, cela ne fait que gratter les données de la première page k fois avec "k" étant le nombre de fois que le navigateur fait défiler vers le bas.
Peter Lenaers
72

Si vous souhaitez faire défiler vers le bas de la page infinie (comme linkedin.com ), vous pouvez utiliser ce code:

SCROLL_PAUSE_TIME = 0.5

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

Référence: https://stackoverflow.com/a/28928684/1316860

Cuong Tran
la source
C'est bien. Pour tous ceux qui essaient d'utiliser cela sur instagram, vous devrez peut-être d'abord cliquer sur le bouton "Charger plus" en utilisant ActionChains, puis appliquer la solution de Cuong Tran ... du moins c'est ce qui a fonctionné pour moi.
Mwspencer
Merci d'avoir répondu! Ce que je voudrais faire, c'est faire défiler par exemple dans instagram vers le bas de la page, puis récupérer le html entier de la page. Y a-t-il une fonction dans le sélénium où je pourrais donner last_height en entrée et obtenir la page entière html, après avoir fait défiler vers le bas?
Swan87
2
Le SCROLL_PAUSE_TIMEvarie, cela prend environ 2 secondes pour moi.
ssi-anik
21

même méthode que celle illustrée ici :

en python, vous pouvez simplement utiliser

driver.execute_script("window.scrollTo(0, Y)")

(Y est la position verticale vers laquelle vous voulez faire défiler)

Lukeis
la source
15
element=find_element_by_xpath("xpath of the li you are trying to access")

element.location_once_scrolled_into_view

cela m'a aidé lorsque j'essayais d'accéder à un «li» qui n'était pas visible.

prémonition
la source
'find_element_by_xpath' est une fonction de pilote ou quoi, le '.location_once_scrolled_into_view' renvoie l'erreur NoSuchElementException: Message: no such element: Impossible de localiser l'élément: {"method": "xpath", "selector": "// * [@ id = "timeline-medley"] / div / div [2] / div [1] "}
Walid Bousseta
Encore une chose. La raison pour laquelle location_once_scrolled_into_viewdevrait être appelé sans () est que location_once_scrolled_into_viewc'est un Python property. voir le code source ici: selenium / webelement.py à d3b6ad006bd7dbee59f8539d81cee4f06bd81d64 · SeleniumHQ / sélénium
DataAlchemist
10

Dans mon but, je voulais faire défiler plus vers le bas, en gardant à l'esprit la position des fenêtres. Ma solution était similaire et utiliséewindow.scrollY

driver.execute_script("window.scrollTo(0, window.scrollY + 200)")

qui ira à la position de défilement y actuelle + 200

Nick Brady
la source
8

Voici comment vous faites défiler la page Web:

driver.execute_script("window.scrollTo(0, 1000);")
sahaja nadendla
la source
7

Le moyen le plus simple que j'ai trouvé pour résoudre ce problème était de sélectionner une étiquette, puis d'envoyer:

label.sendKeys(Keys.PAGE_DOWN);

Esperons que ça marche!

Juanse
la source
6

Aucune de ces réponses n'a fonctionné pour moi, du moins pas pour faire défiler une page de résultats de recherche Facebook, mais j'ai trouvé après de nombreux tests cette solution:

while driver.find_element_by_tag_name('div'):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    Divs=driver.find_element_by_tag_name('div').text
    if 'End of Results' in Divs:
        print 'end'
        break
    else:
        continue
Bass Dee
la source
Cela fonctionne, mais très lentement (pour moi du moins). Je trouve que si vous définissez SCROLL_PAUSE_TIMEdans stackoverflow.com/a/27760083/7326714 pour 2, cela fonctionne très bien et vous faites défiler vers le bas un 100x plus rapide.
LucSpan
6

Lorsque vous travaillez avec youtube, les éléments flottants donnent la valeur "0" comme hauteur de défilement, donc plutôt que d'utiliser "return document.body.scrollHeight" essayez d'utiliser celui-ci "return document.documentElement.scrollHeight" ajustez le temps de pause du défilement selon votre Internet vitesse sinon, il ne fonctionnera qu'une seule fois, puis se cassera après cela.

SCROLL_PAUSE_TIME = 1

# Get scroll height
"""last_height = driver.execute_script("return document.body.scrollHeight")

this dowsnt work due to floating web elements on youtube
"""

last_height = driver.execute_script("return document.documentElement.scrollHeight")
while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0,document.documentElement.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.documentElement.scrollHeight")
    if new_height == last_height:
       print("break")
       break
    last_height = new_height
Vinay Verma
la source
5

Je cherchais un moyen de faire défiler une page Web dynamique, et de m'arrêter automatiquement une fois que la fin de la page est atteinte, et j'ai trouvé ce fil.

Le message de @Cuong Tran , avec une modification principale, était la réponse que je recherchais. J'ai pensé que d'autres pourraient trouver la modification utile (elle a un effet prononcé sur le fonctionnement du code), d'où cet article.

La modification consiste à déplacer l'instruction qui capture la dernière hauteur de page à l' intérieur de la boucle (de sorte que chaque vérification soit comparée à la hauteur de page précédente).

Donc, le code ci-dessous:

Fait continuellement défiler une page Web dynamique ( .scrollTo()), ne s'arrêtant que lorsque, pour une itération, la hauteur de la page reste la même.

(Il y a une autre modification, où l'instruction break est à l'intérieur d'une autre condition (au cas où la page «colle») qui peut être supprimée).

    SCROLL_PAUSE_TIME = 0.5


    while True:

        # Get scroll height
        ### This is the difference. Moving this *inside* the loop
        ### means that it checks if scrollTo is still scrolling 
        last_height = driver.execute_script("return document.body.scrollHeight")

        # Scroll down to bottom
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

        # Wait to load page
        time.sleep(SCROLL_PAUSE_TIME)

        # Calculate new scroll height and compare with last scroll height
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:

            # try again (can be removed)
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

            # Wait to load page
            time.sleep(SCROLL_PAUSE_TIME)

            # Calculate new scroll height and compare with last scroll height
            new_height = driver.execute_script("return document.body.scrollHeight")

            # check if the page height has remained the same
            if new_height == last_height:
                # if so, you are done
                break
            # if not, move on to the next loop
            else:
                last_height = new_height
                continue
Splarty
la source
5

Ce code défile vers le bas mais ne nécessite pas d'attendre à chaque fois. Il défilera continuellement, puis s'arrêtera en bas (ou expiration du délai)

from selenium import webdriver
import time

driver = webdriver.Chrome(executable_path='chromedriver.exe')
driver.get('https://example.com')

pre_scroll_height = driver.execute_script('return document.body.scrollHeight;')
run_time, max_run_time = 0, 1
while True:
    iteration_start = time.time()
    # Scroll webpage, the 100 allows for a more 'aggressive' scroll
    driver.execute_script('window.scrollTo(0, 100*document.body.scrollHeight);')

    post_scroll_height = driver.execute_script('return document.body.scrollHeight;')

    scrolled = post_scroll_height != pre_scroll_height
    timed_out = run_time >= max_run_time

    if scrolled:
        run_time = 0
        pre_scroll_height = post_scroll_height
    elif not scrolled and not timed_out:
        run_time += time.time() - iteration_start
    elif not scrolled and timed_out:
        break

# closing the driver is optional 
driver.close()

C'est beaucoup plus rapide que d'attendre 0,5 à 3 secondes à chaque fois pour une réponse, lorsque cette réponse peut prendre 0,1 seconde

AlbertWolfgang
la source
3

faire défiler les pages de chargement. Exemple: medium, quora, etc.

last_height = driver.execute_script("return document.body.scrollHeight")
    while True:
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight-1000);")
        # Wait to load the page.
        driver.implicitly_wait(30) # seconds
        new_height = driver.execute_script("return document.body.scrollHeight")
    
        if new_height == last_height:
            break
        last_height = new_height
        # sleep for 30s
        driver.implicitly_wait(30) # seconds
    driver.quit()
ashishmishra
la source
1
driver.quit () doit-il être en dehors du bloc while ou non? et aussi la dernière attente implicite n'est pas requise .. quelqu'un veuillez confirmer. @ashishmishra
ihightower
1

si vous souhaitez faire défiler une vue / un cadre particulier (WebElement), il vous suffit de remplacer "corps" par un élément particulier dans lequel vous avez l'intention de faire défiler. j'obtiens cet élément via "getElementById" dans l'exemple ci-dessous:

self.driver.execute_script('window.scrollTo(0, document.getElementById("page-manager").scrollHeight);')

c'est le cas sur YouTube , par exemple ...

Furkan Unluturk
la source
1

La ScrollTo()fonction ne fonctionne plus. C'est ce que j'ai utilisé et cela a bien fonctionné.

driver.execute_script("document.getElementById('mydiv').scrollIntoView();")
MoKG
la source
Seule cette méthode a fonctionné dans mon cas, aucune autre n'a fonctionné. Merci.
ePandit
0
driver.execute_script("document.getElementById('your ID Element').scrollIntoView();")

ça marche pour mon cas.

Long Lê Hoàng
la source