Como posso rolar uma página da web usando o selenium webdriver em python?

132

Atualmente, estou usando o selenium webdriver para analisar a página de amigos do usuário do Facebook e extrair todos os IDs do script AJAX. Mas preciso rolar para baixo para conseguir todos os amigos. Como posso rolar para baixo no Selenium. Eu estou usando python.

user2523364
fonte
2
possível duplicata Como rolar a página com selênio
Louis
driver.execute_script (f "window.scrollTo (0, {2 ** 127});")
AturSams

Respostas:

264

Você pode usar

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

onde Y é a altura (em um monitor fullhd é 1080). (Graças a @lukeis)

Você também pode usar

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

para rolar até o final da página.

Se você quiser rolar para uma página com carregamento infinito , como os de redes sociais, facebook etc. (graças a @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

outro método (graças a Juanse) é, selecione um objeto e

label.sendKeys(Keys.PAGE_DOWN);
OWADVL
fonte
1
Excelente, você pode explicar um pouco sobre scrollHeighto que isso significa e como funciona em geral?
Jason Goal
Como você usaria a variável "last_height"? Tenho algo semelhante no meu código e o navegador está rolando para baixo. No entanto, quando olho para os dados que estou raspando, eles apenas raspam os dados da primeira página k vezes com "k" sendo o número de vezes que o navegador rola para baixo.
Peter Lenaers
72

Se você quiser rolar para a parte inferior da página infinita (como linkedin.com ), use este código:

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

Referência: https://stackoverflow.com/a/28928684/1316860

Cuong Tran
fonte
Isso é ótimo. Para quem está tentando usar isso no instagram, pode ser necessário primeiro aba no botão "Carregar mais" usando o ActionChains e aplicar a solução da Cuong Tran ... pelo menos foi o que funcionou para mim.
Mwspencer
Obrigado pela resposta! O que eu gostaria de fazer é rolar, por exemplo, no instagram, para a parte inferior da página, e depois pegar o html inteiro da página. Existe uma função no selênio onde eu poderia fornecer last_height como entrada e obter o html da página inteira, depois de rolar para o final?
Swan87
2
O SCROLL_PAUSE_TIMEvaria, leva cerca de 2 segundos para mim.
ssi-anik
21

mesmo método como mostrado aqui :

em python, você pode simplesmente usar

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

(Y é a posição vertical na qual você deseja rolar)

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

element.location_once_scrolled_into_view

isso ajudou quando eu estava tentando acessar um 'li' que não era visível.

premonição
fonte
'find_element_by_xpath' é uma função de driver ou o que, o '.location_once_scrolled_into_view' retorna o erro NoSuchElementException: Mensagem: não existe esse elemento: não é possível localizar o elemento: {"method": "xpath", "selector": "// * [@ id = "timeline-medley"] / div / div [2] / div [1] "}
Walid Bousseta
Só mais uma coisa. A razão pela qual location_once_scrolled_into_viewdeve ser chamado de sem () é que location_once_scrolled_into_viewé um Python property. veja o código-fonte aqui: selenium / webelement.py em d3b6ad006bd7dbee59f8539d81cee4f06bd81d64 · SelenHQ / selênio
DataAlchemist
10

Para o meu propósito, eu queria rolar mais para baixo, mantendo a posição das janelas em mente. Minha solução foi semelhante e usadawindow.scrollY

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

que irá para a posição atual de rolagem y + 200

Nick Brady
fonte
8

É assim que você rola a página da Web:

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

A maneira mais fácil de solucionar esse problema foi selecionar um rótulo e enviar:

label.sendKeys(Keys.PAGE_DOWN);

Espero que funcione!

Juanse
fonte
6

Nenhuma dessas respostas funcionou para mim, pelo menos não para rolar uma página de resultados de pesquisa do Facebook, mas descobri depois de muito teste esta solução:

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
fonte
Funciona, mas muito lento (pelo menos para mim). Descobri que se você definir SCROLL_PAUSE_TIMEem stackoverflow.com/a/27760083/7326714 para 2, ele funciona muito bem e você rolar para baixo a 100x mais rápido.
LucSpan
6

Ao trabalhar com o youtube, os elementos flutuantes fornecem o valor "0" como a altura da rolagem, em vez de usar "return document.body.scrollHeight", tente usar este "return document.documentElement.scrollHeight" para ajustar o tempo de pausa da rolagem conforme sua Internet velocidade, caso contrário, ele será executado apenas uma vez e depois será interrompido.

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

Eu estava procurando uma maneira de percorrer uma página da web dinâmica e parar automaticamente assim que o final da página fosse alcançado e encontrei este tópico.

O post de @Cuong Tran , com uma modificação principal, foi a resposta que eu estava procurando. Eu pensei que outros pudessem achar a modificação útil (ela tem um efeito pronunciado sobre como o código funciona), por isso neste post.

A modificação é mover a instrução que captura a última altura da página dentro do loop (para que cada verificação seja comparada à altura da página anterior).

Então, o código abaixo:

Rola continuamente uma página da Web dinâmica ( .scrollTo()), parando apenas quando, por uma iteração, a altura da página permanece a mesma.

(Há outra modificação, em que a instrução break está dentro de outra condição (caso a página 'fique') que pode ser removida).

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

Esse código rola até o final, mas não exige que você espere cada vez. Ele rolará continuamente e depois parará na parte inferior (ou tempo limite)

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

Isso é muito mais rápido do que esperar 0,5 a 3 segundos cada vez por uma resposta, quando essa resposta pode levar 0,1 segundos

AlbertWolfgang
fonte
3

rolar páginas de carregamento. Exemplo: médio, 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
fonte
1
driver.quit () deve estar fora do bloco while ou não? e também a última espera implícita não é necessária. alguém confirma. @ashishmishra
ihightower 24/07
1

se você quiser rolar dentro de uma exibição / quadro específica (WebElement), o que você precisa fazer é substituir "corpo" por um elemento específico no qual você deseja rolar. eu recebo esse elemento via "getElementById" no exemplo abaixo:

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

é o caso do YouTube , por exemplo ...

Furkan Unluturk
fonte
1

A ScrollTo()função não funciona mais. Isto é o que eu usei e funcionou bem.

driver.execute_script("document.getElementById('mydiv').scrollIntoView();")
MoKG
fonte
Somente esse método funcionou no meu caso, não outro funcionou. Obrigado.
ePandit
0
driver.execute_script("document.getElementById('your ID Element').scrollIntoView();")

está funcionando para o meu caso.

Long Lê Hoàng
fonte