Wie kann ich mit Selenium Webdriver in Python eine Webseite scrollen?

129

Ich verwende derzeit Selenium Webdriver, um die Facebook-Seite mit Freunden von Freunden zu analysieren und alle IDs aus dem AJAX-Skript zu extrahieren. Aber ich muss nach unten scrollen, um alle Freunde zu bekommen. Wie kann ich in Selen nach unten scrollen? Ich benutze Python.

user2523364
quelle
2
Mögliches Duplikat von Wie man eine Seite mit Selen
Louis
driver.execute_script (f "window.scrollTo (0, {2 ** 127});")
AturSams

Antworten:

261

Sie können verwenden

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

Dabei ist Y die Höhe (auf einem Full-HD-Monitor sind es 1080). (Danke an @lukeis)

Sie können auch verwenden

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

um zum Ende der Seite zu scrollen .

Wenn Sie zu einer Seite mit unendlichem Laden scrollen möchten , z. B. zu sozialen Netzwerken, Facebook usw. (danke an @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

Eine andere Methode (dank Juanse) ist, ein Objekt auszuwählen und

label.sendKeys(Keys.PAGE_DOWN);
OWADVL
quelle
1
Ausgezeichnet, können Sie ein wenig erklären scrollHeight, was es bedeutet und wie es im Allgemeinen funktioniert?
Jason Goal
Wie würden Sie dann die Variable "last_height" verwenden? Ich habe etwas Ähnliches in meinem Code und der Browser scrollt nach unten. Wenn ich mir jedoch die Daten ansehe, die ich kratzt, kratzt es nur die Daten von der ersten Seite k-mal, wobei "k" die Häufigkeit ist, mit der der Browser nach unten scrollt.
Peter Lenaers
72

Wenn Sie zum Ende der unendlichen Seite scrollen möchten (wie linkedin.com ), können Sie diesen Code verwenden:

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

Referenz: https://stackoverflow.com/a/28928684/1316860

Cuong Tran
quelle
Das ist toll. Für alle, die versuchen, dies auf Instagram zu verwenden, müssen Sie möglicherweise zuerst mit ActionChains auf die Schaltfläche "Mehr laden" klicken und dann die Lösung von Cuong Tran anwenden ... zumindest hat das bei mir funktioniert.
Mwspencer
Danke für die Antwort! Was ich tun möchte, ist zum Beispiel in Instagram zum Ende der Seite zu scrollen und dann das gesamte HTML der Seite abzurufen. Gibt es eine Funktion in Selen, bei der ich last_height als Eingabe angeben und die gesamte HTML-Seite abrufen kann, nachdem ich nach unten gescrollt habe?
Swan87
2
Das SCROLL_PAUSE_TIMEvariiert, es dauert ungefähr 2 Sekunden für mich.
SSI-Anik
30

Sie können send_keyseinen END(oder PAGE_DOWN) Tastendruck simulieren (der normalerweise die Seite scrollt):

from selenium.webdriver.common.keys import Keys
html = driver.find_element_by_tag_name('html')
html.send_keys(Keys.END)
LIU YUE
quelle
21

gleiche Methode wie hier gezeigt :

In Python können Sie einfach verwenden

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

(Y ist die vertikale Position, zu der Sie scrollen möchten)

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

element.location_once_scrolled_into_view

Dies half, als ich versuchte, auf ein 'li' zuzugreifen, das nicht sichtbar war.

Vorahnung
quelle
'find_element_by_xpath' ist eine Treiberfunktion oder was, die '.location_once_scrolled_into_view' gibt den Fehler NoSuchElementException zurück: Nachricht: kein solches Element: Element kann nicht gefunden werden: {"method": "xpath", "selector": "// * [@ id = "timeline-medley"] / div / div [2] / div [1] "}
Walid Bousseta
Nur noch eine Sache. Der Grund, warum location_once_scrolled_into_viewohne aufgerufen werden sollte, () ist, dass location_once_scrolled_into_viewes sich um einen Python handelt property. Den Quellcode finden Sie hier: selenium / webelement.py unter d3b6ad006bd7dbee59f8539d81cee4f06bd81d64 · SeleniumHQ /
selenium
10

Zu meinem Zweck wollte ich mehr nach unten scrollen und dabei die Position der Fenster berücksichtigen. Meine Lösung war ähnlich und verwendetwindow.scrollY

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

Dies wird zur aktuellen y-Bildlaufposition + 200 gehen

Nick Brady
quelle
8

So scrollen Sie auf der Webseite nach unten:

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

Der einfachste Weg, dieses Problem zu lösen, bestand darin, ein Etikett auszuwählen und dann zu senden:

label.sendKeys(Keys.PAGE_DOWN);

Hoffe, es funktioniert!

Juanse
quelle
6

Keine dieser Antworten hat bei mir funktioniert, zumindest nicht beim Scrollen einer Facebook-Suchergebnisseite, aber ich habe nach vielen Tests dieser Lösung Folgendes gefunden:

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
quelle
Es funktioniert, aber sehr langsam (zumindest für mich). Ich habe festgestellt, dass wenn Sie SCROLL_PAUSE_TIMEin stackoverflow.com/a/27760083/7326714 auf setzen 2, es gut funktioniert und Sie 100x schneller nach unten scrollen.
LucSpan
6

Wenn Sie mit YouTube arbeiten, geben die schwebenden Elemente den Wert "0" als Bildlaufhöhe an. Verwenden Sie also "return document.body.scrollHeight" , anstatt "return document.documentElement.scrollHeight" zu verwenden. Passen Sie die Bildlaufpausenzeit gemäß Ihrem Internet an Geschwindigkeit sonst läuft es nur einmal und bricht danach ab.

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
quelle
5

Ich suchte nach einer Möglichkeit, durch eine dynamische Webseite zu scrollen und automatisch anzuhalten, sobald das Ende der Seite erreicht ist, und fand diesen Thread.

Der Beitrag von @Cuong Tran mit einer Hauptänderung war die Antwort, nach der ich gesucht habe. Ich dachte, dass andere die Änderung hilfreich finden könnten (sie hat einen ausgeprägten Einfluss auf die Funktionsweise des Codes), daher dieser Beitrag.

Die Änderung besteht darin, die Anweisung zu verschieben, die die letzte Seitenhöhe innerhalb der Schleife erfasst (sodass jede Prüfung mit der vorherigen Seitenhöhe verglichen wird).

Also, der Code unten:

Scrollt kontinuierlich eine dynamische Webseite ( .scrollTo()) nach unten und stoppt nur, wenn für eine Iteration die Seitenhöhe gleich bleibt.

(Es gibt eine weitere Änderung, bei der sich die break-Anweisung in einer anderen Bedingung befindet (falls die Seite "klebt"), die entfernt werden kann.)

    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
quelle
5

Dieser Code scrollt nach unten, erfordert jedoch nicht, dass Sie jedes Mal warten. Es wird kontinuierlich gescrollt und dann unten angehalten (oder Timeout)

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

Dies ist viel schneller als jedes Mal 0,5 bis 3 Sekunden auf eine Antwort zu warten, wenn diese Antwort 0,1 Sekunden dauern kann

AlbertWolfgang
quelle
3

Bildlaufseiten scrollen. Beispiel: Medium, Quora usw.

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
quelle
sollte driver.quit () außerhalb des while-Blocks liegen oder nicht? und auch das letzte implizite Warten ist nicht erforderlich .. jemand pls bestätigen. @ashishmishra
ihightower
1

Wenn Sie innerhalb einer bestimmten Ansicht / eines bestimmten Rahmens (WebElement) scrollen möchten, müssen Sie nur "body" durch ein bestimmtes Element ersetzen, in dem Sie scrollen möchten . Ich erhalte dieses Element über "getElementById" im folgenden Beispiel:

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

Dies ist zum Beispiel bei YouTube der Fall ...

Furkan Unluturk
quelle
1

Die ScrollTo()Funktion funktioniert nicht mehr. Das habe ich benutzt und es hat gut funktioniert.

driver.execute_script("document.getElementById('mydiv').scrollIntoView();")
MoKG
quelle
Nur diese Methode hat in meinem Fall funktioniert, andere nicht. Vielen Dank.
ePandit
0
driver.execute_script("document.getElementById('your ID Element').scrollIntoView();")

es funktioniert für meinen Fall.

Long Lê Hoàng
quelle