Jak przewijać stronę internetową za pomocą selenium webdriver w Pythonie?

131

Obecnie używam webdrivera selenu do analizowania strony znajomych na Facebooku i wyodrębniania wszystkich identyfikatorów ze skryptu AJAX. Ale muszę przewinąć w dół, aby znaleźć wszystkich przyjaciół. Jak mogę przewinąć w dół w Selenium. Używam Pythona.

user2523364
źródło
2
możliwy duplikat Jak przewijać stronę z selenem
Louis
driver.execute_script (f "window.scrollTo (0, {2 ** 127});")
AturSams,

Odpowiedzi:

263

Możesz użyć

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

gdzie Y to wysokość (na monitorze FullHD jest to 1080). (Dzięki @lukeis)

Możesz także użyć

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

aby przewinąć do dołu strony.

Jeśli chcesz przewinąć do strony z nieskończonym ładowaniem , takiej jak strony społecznościowe, facebook itp. (Dzięki @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

inną metodą (dzięki Juanse) jest wybranie obiektu i

label.sendKeys(Keys.PAGE_DOWN);
OWADVL
źródło
1
Wspaniale, czy możesz trochę wyjaśnić scrollHeight, co to oznacza i jak ogólnie działa?
Jason Goal
W jaki sposób użyłbyś zmiennej „last_height”? Mam coś podobnego w moim kodzie, a przeglądarka przewija się w dół. Jednak kiedy patrzę na dane, które skrobam, tylko zeskrobuje dane z pierwszej strony k razy, gdzie „k” oznacza liczbę przewinięć przeglądarki w dół.
Peter Lenaers
72

Jeśli chcesz przewinąć w dół nieskończoną stronę (np. Linkedin.com ), możesz użyć tego kodu:

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ódła: https://stackoverflow.com/a/28928684/1316860

Cuong Tran
źródło
To jest świetne. Dla każdego, kto próbuje użyć tego na Instagramie, być może będziesz musiał najpierw przejść do przycisku „Załaduj więcej” za pomocą ActionChains, a następnie zastosować rozwiązanie Cuong Tran… przynajmniej to zadziałało dla mnie.
Mwspencer
Dziękuję za odpowiedź! Chciałbym np. Przewinąć instagram na dół strony, a następnie pobrać cały html strony. Czy w selenie jest funkcja, w której mógłbym podać last_height jako dane wejściowe i pobrać cały kod HTML strony po przewinięciu do dołu?
Swan87
2
W SCROLL_PAUSE_TIMERóżnie, trwa około 2 sekundy dla mnie.
ssi-anik
21

ta sama metoda, jak pokazano tutaj :

w Pythonie możesz po prostu użyć

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

(Y to pozycja w pionie, do której chcesz przewinąć)

lukeis
źródło
15
element=find_element_by_xpath("xpath of the li you are trying to access")

element.location_once_scrolled_into_view

pomogło to, gdy próbowałem uzyskać dostęp do „li”, które nie było widoczne.

przeczucie
źródło
„find_element_by_xpath” to funkcja sterownika lub co, „.location_once_scrolled_into_view” zwraca błąd NoSuchElementException: Message: no such element: Nie można zlokalizować elementu: {"method": "xpath", "selector": "// * [@ id = "timeline-medley"] / div / div [2] / div [1] "}
Walid Bousseta
Jeszcze jedna rzecz. Powodem, dla którego location_once_scrolled_into_viewpowinno się wywoływać bez, () jest to, że location_once_scrolled_into_viewjest to Python property. zobacz kod źródłowy tutaj: selenium / webelement.py pod adresem d3b6ad006bd7dbee59f8539d81cee4f06bd81d64 · SeleniumHQ / selenium
DataAlchemist
10

W moim celu chciałem bardziej przewijać w dół, pamiętając o położeniu okien. Moje rozwiązanie było podobne i używanewindow.scrollY

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

który przejdzie do aktualnej pozycji przewijania y + 200

Nick Brady
źródło
8

Oto jak przewijasz stronę w dół:

driver.execute_script("window.scrollTo(0, 1000);")
sahaja nadendla
źródło
7

Najłatwiejszym sposobem rozwiązania tego problemu było wybranie etykiety, a następnie wysłanie:

label.sendKeys(Keys.PAGE_DOWN);

Mam nadzieję, że to działa!

Juanse
źródło
6

Żadna z tych odpowiedzi nie działała dla mnie, przynajmniej nie do przewijania strony wyników wyszukiwania na Facebooku, ale po wielu testach znalazłem to rozwiązanie:

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
źródło
Działa, ale bardzo wolno (przynajmniej dla mnie). Okazało się, że jeśli ustawisz SCROLL_PAUSE_TIMEw stackoverflow.com/a/27760083/7326714 się 2, że działa dobrze i przewijania w dół 100x szybsze.
LucSpan
6

Podczas pracy z YouTube elementy pływające podają wartość „0” jako wysokość przewijania, więc zamiast używać „return document.body.scrollHeight” spróbuj użyć tego jednego „return document.documentElement.scrollHeight” dostosuj czas wstrzymania przewijania zgodnie z Twoim Internetem W przeciwnym razie będzie działać tylko jeden raz, a następnie zepsuje się.

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
źródło
5

Szukałem sposobu na przewijanie dynamicznej strony internetowej i automatyczne zatrzymywanie po osiągnięciu końca strony i znalezieniu tego wątku.

Post od @Cuong Tran , z jedną główną modyfikacją, był odpowiedzią, której szukałem. Pomyślałem, że inni mogą uznać modyfikację za pomocną (ma ona wyraźny wpływ na działanie kodu), stąd ten post.

Modyfikacja polega na przeniesieniu instrukcji przechwytującej wysokość ostatniej strony wewnątrz pętli (tak, aby każde sprawdzenie było porównywane z wysokością poprzedniej strony).

Tak więc poniższy kod:

Ciągle przewija dynamiczną stronę internetową w dół ( .scrollTo()), zatrzymując się tylko wtedy, gdy w jednej iteracji wysokość strony pozostaje taka sama.

(Jest jeszcze jedna modyfikacja, w której instrukcja break znajduje się w innym warunku (w przypadku, gdy strona się zacina), który można usunąć).

    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
źródło
5

Ten kod przewija się do dołu, ale nie wymaga za każdym razem czekania. Będzie się stale przewijać, a następnie zatrzymywać na dole (lub po przekroczeniu limitu czasu)

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

Jest to znacznie szybsze niż oczekiwanie 0,5-3 sekund za każdym razem na odpowiedź, kiedy ta odpowiedź może zająć 0,1 sekundy

AlbertWolfgang
źródło
3

Przewiń ładowanie stron. Przykład: medium, quora itp

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
źródło
1
czy driver.quit () powinien znajdować się poza blokiem while, czy nie? a także ostatnie niejawne oczekiwanie nie jest wymagane .. ktoś potwierdza. @ashishmishra
ihightower
1

jeśli chcesz przewijać w określonym widoku / ramce (WebElement), jedyne, co musisz zrobić, to zastąpić „body” określonym elementem, który chcesz przewijać. otrzymuję ten element poprzez „getElementById” w poniższym przykładzie:

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

tak jest na przykład w YouTube ...

Furkan Unluturk
źródło
1

Ta ScrollTo()funkcja już nie działa. To jest to, czego użyłem i działało dobrze.

driver.execute_script("document.getElementById('mydiv').scrollIntoView();")
MoKG
źródło
Tylko ta metoda zadziałała w moim przypadku, inne nie zadziałały. Dzięki.
ePandit
0
driver.execute_script("document.getElementById('your ID Element').scrollIntoView();")

to działa w moim przypadku.

Long Lê Hoàng
źródło