【问题标题】:How can I scroll a web page using selenium webdriver in python?如何在 python 中使用 selenium webdriver 滚动网页?
【发布时间】:2014-01-26 00:30:26
【问题描述】:

我目前正在使用 selenium webdriver 来解析 facebook 用户朋友页面并从 AJAX 脚本中提取所有 id。但我需要向下滚动以获取所有朋友。如何在 Selenium 中向下滚动。我正在使用 python。

【问题讨论】:

  • driver.execute_script(f"window.scrollTo(0, {2**127});")
  • 如果你的情况有一个项目列表,那么你可以按照这个方法stackoverflow.com/a/68970174/12272687

标签: python selenium selenium-webdriver automated-tests


【解决方案1】:

方法同here

在python中你可以使用

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

(Y是你要滚动到的垂直位置)

【讨论】:

    【解决方案2】:

    您可以使用

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

    其中 Y 是高度(在全高清显示器上为 1080)。 (感谢@lukeis)

    您也可以使用

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

    滚动到页面底部。

    如果您希望滚动到无限加载的页面,例如社交网络、Facebook 等(感谢@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
    

    另一种方法(感谢 Juanse)是,选择一个对象并

    label.sendKeys(Keys.PAGE_DOWN);
    

    【讨论】:

    • 太好了,你能在scrollHeight上稍微解释一下,它是什么意思,它是如何工作的?
    • 你将如何使用变量“last_height”?我的代码中有类似的东西,浏览器正在向下滚动。但是,当我查看正在抓取的数据时,它只会从第一页抓取数据 k 次,其中“k”是浏览器向下滚动的次数。
    • @JasonGoal 希望这会有所帮助:stackoverflow.com/a/22675563/6907424
    • driver.execute_script 可以结合平滑滚动 (developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo) 来模仿更像人类的行为!
    【解决方案3】:
    element=find_element_by_xpath("xpath of the li you are trying to access")
    
    element.location_once_scrolled_into_view
    

    这在我尝试访问不可见的“li”时有所帮助。

    【讨论】:

    • 'find_element_by_xpath' 是驱动函数还是什么,'.location_once_scrolled_into_view' 返回错误 NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector" :"//*[@id="timeline-medley"]/div/div[2]/div[1]"}
    • 还有一件事。 location_once_scrolled_into_view 应该在没有 () 的情况下调用的原因是 location_once_scrolled_into_view 是 Python property。在此处查看源代码:selenium/webelement.py at d3b6ad006bd7dbee59f8539d81cee4f06bd81d64 · SeleniumHQ/selenium
    【解决方案4】:

    如果你想向下滚动到无限页面的底部(如linkedin.com),你可以使用这个代码:

    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
    

    参考:https://stackoverflow.com/a/28928684/1316860

    【讨论】:

    • 这很棒。对于尝试在 Instagram 上使用此功能的任何人,您可能需要先使用 ActionChains 将选项卡转到“加载更多”按钮,然后应用 Cuong Tran 的解决方案……至少这对我有用。
    • 感谢您的回答!我想做的是例如在 instagram 中滚动到页面底部,然后抓取页面的整个 html。 selenium 中是否有一个函数可以在我滚动到底部后将 last_height 作为输入并获取整个页面的 html?
    • SCROLL_PAUSE_TIME 各不相同,对我来说大约需要 2 秒。
    【解决方案5】:

    这些答案都不适合我,至少不适用于向下滚动 facebook 搜索结果页面,但经过大量测试此解决方案后我发现:

    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
    

    【讨论】:

    • 它可以工作,但是很慢(至少对我来说)。我发现如果你将stackoverflow.com/a/27760083/7326714 中的SCROLL_PAUSE_TIME 设置为2,它工作得很好,而且你向下滚动的速度提高了100 倍。
    【解决方案6】:

    我发现解决该问题的最简单方法是选择一个标签,然后发送:

    label.sendKeys(Keys.PAGE_DOWN);
    

    希望它有效!

    【讨论】:

      【解决方案7】:

      您可以使用send_keys 模拟END (or PAGE_DOWN) key press(通常滚动页面):

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

      【讨论】:

      • 在循环中尝试了 PAGE_DOWN 并且没有按预期运行,END 出于 w/e 原因按预期工作
      【解决方案8】:

      出于我的目的,我想向下滚动更多,同时牢记窗口位置。我的解决方案类似并使用了window.scrollY

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

      将转到当前的 y 滚动位置 + 200

      【讨论】:

        【解决方案9】:

        我正在寻找一种滚动动态网页的方法,并在到达页面末尾时自动停止,并找到了这个线程。

        @Cuong Tran 的帖子经过一项主要修改,正是我正在寻找的答案。我认为其他人可能会发现修改很有帮助(它对代码的工作方式有显着影响),因此这篇文章。

        修改是将捕获最后一页高度的语句移动到内部循环中(以便每次检查都与上一页高度进行比较)。

        所以,下面的代码:

        持续向下滚动动态网页 (.scrollTo()),仅在一次迭代中页面高度保持不变时停止。

        (还有另一种修改,break 语句位于另一个可以删除的条件(以防页面“粘住”)内)。

            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
        

        【讨论】:

          【解决方案10】:

          这是您向下滚动网页的方式:

          driver.execute_script("window.scrollTo(0, 1000);")
          

          【讨论】:

            【解决方案11】:

            使用 youtube 时,浮动元素将值“0”作为滚动高度 所以不要使用 "return document.body.scrollHeight" 尝试使用这个 "return document.documentElement.scrollHeight" 根据您的网速调整滚动暂停时间 否则它将只运行一次然后中断。

            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
            

            【讨论】:

              【解决方案12】:

              滚动加载页面。示例:medium、quora 等

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

              【讨论】:

              • driver.quit() 是否应该在 while 块之外?并且不需要最后的隐式等待..有人请确认。 @ashishmishra
              • 不,如果 driver.quit() 在 while 循环内,驱动程序将在循环的每次迭代中关闭。一旦页面没有更多长度,它将退出。最后一次等待可能是为了让页面有时间加载?
              【解决方案13】:

              此代码滚动到底部,但不需要您每次都等待。它会不断滚动,然后停在底部(或超时)

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

              这比每次等待 0.5-3 秒等待响应要快得多,因为响应可能需要 0.1 秒

              【讨论】:

              • 对我不起作用。
              【解决方案14】:

              如果您想在特定视图/框架内滚动 (WebElement),您只需将“body”替换为您打算在其中滚动的特定元素。我在下面的示例中通过“getElementById”获取该元素:

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

              YouTube 上就是这种情况,例如...

              【讨论】:

                【解决方案15】:

                ScrollTo() 函数不再起作用。这是我用过的,效果很好。

                driver.execute_script("document.getElementById('mydiv').scrollIntoView();")
                

                【讨论】:

                • 只有这种方法在我的情况下有效,其他方法无效。谢谢。
                • 也为我工作。如果您多次调用 scrollIntoView,请务必设置 setTimeout() 函数以允许页面加载新内容,否则它将找不到新元素。附带说明一下,要通过 href 查找元素,您可以执行以下操作: driver.execute_script(document.querySelector(\"a[href=\'your_href_link\']\").scrollIntoView();")
                【解决方案16】:
                driver.execute_script("document.getElementById('your ID Element').scrollIntoView();")
                

                它适用于我的情况。

                【讨论】:

                  【解决方案17】:

                  这是一个示例 selenium 代码 sn-p,您可以将其用于此类目的。它转到“枚举 python 教程”上的 youtube 搜索结果的 url 并向下滚动,直到找到标题为“枚举 python 教程(2020)”的视频。

                  driver.get('https://www.youtube.com/results?search_query=enumerate+python')
                  target = driver.find_element_by_link_text('Enumerate python tutorial(2020).')
                  target.location_once_scrolled_into_view
                  

                  【讨论】:

                    【解决方案18】:

                    您可以使用 send_keys 模拟 PAGE_DOWN 按键(通常滚动页面):

                    from selenium.webdriver.common.keys import Keys
                    html = driver.find_element_by_tag_name('html')
                    html.send_keys(Keys.PAGE_DOWN)
                    

                    【讨论】:

                    • 就是this answer,只是比较模糊
                    • 这是我工作的特定页面上唯一适用于我的代码,但我必须用鼠标单击滑块才能工作我不知道为什么我应该这样做,我尝试找到另一个我的问题的解决方案
                    • 我工作的页面:contacts.google.com/u/0/directory
                    【解决方案19】:

                    插入这一行driver.execute_script("window.scrollBy(0,925)", "")

                    【讨论】:

                    • 虽然这段代码可能会回答这个问题,including an explanation 关于如何或为什么解决问题将真正有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的答案添加解释并说明适用的限制和假设。
                    猜你喜欢
                    • 2023-03-12
                    • 2014-11-10
                    • 2020-01-15
                    • 2019-02-10
                    • 2018-09-20
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多