剧作家自动滚动到无限滚动页面的底部

ale*_*its 16 javascript python python-3.x playwright

我正在尝试使用 Python 和 Playwright 自动抓取具有“无限滚动”功能的网站。

问题是,到目前为止,Playwright 还不包含滚动功能,更不用说无限自动滚动功能了。

根据我在网上发现的内容和我的个人测试,我可以使用该page.evaluate()函数和一些 Javascript 代码自动执行无限或有限滚动。

例如,这有效:

for i in range(20):
    page.evaluate('var div = document.getElementsByClassName("comment-container")[0];div.scrollTop = div.scrollHeight')
    page.wait_for_timeout(500)
Run Code Online (Sandbox Code Playgroud)

这种方法的问题在于,它要么通过指定滚动数量,要么通过告诉它永远循环下去来工作while True

我需要找到一种方法来告诉它继续滚动,直到加载最终内容。

这是我目前正在尝试的 Javascript page.evaluate()

var intervalID = setInterval(function() {
    var scrollingElement = (document.scrollingElement || document.body);
    scrollingElement.scrollTop = scrollingElement.scrollHeight;
    console.log('fail')
}, 1000);
var anotherID = setInterval(function() {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
        clearInterval(intervalID);
    }}, 1000)
Run Code Online (Sandbox Code Playgroud)

这在我的 Firefox 浏览器或 Playwright 的 Firefox 浏览器中都不起作用。它立即返回并且不会间隔执行代码。

如果有人能告诉我如何使用 Playwright 创建一个自动滚动功能,该功能将在到达动态加载网页的底部时检测并停止,我将不胜感激。

ale*_*its 17

所以我找到了一个可行的解决方案。

我所做的是将 Javascript 与 python Playwright 代码结合起来。

我用 200ms 的计时器启动 setInterval 在页面上向下滚动page.evaluate(),然后用 python 循环跟踪它,每秒检查页面的总高度(包括滚动)是否已更改。如果发生变化,则继续滚动,如果没有变化,则滚动结束。
它看起来是这样的:

page.evaluate(
    """
    var intervalID = setInterval(function () {
        var scrollingElement = (document.scrollingElement || document.body);
        scrollingElement.scrollTop = scrollingElement.scrollHeight;
    }, 200);

    """
)
prev_height = None
while True:
    curr_height = page.evaluate('(window.innerHeight + window.scrollY)')
    if not prev_height:
        prev_height = curr_height
        time.sleep(1)
    elif prev_height == curr_height:
        page.evaluate('clearInterval(intervalID)')
        break
    else:
        prev_height = curr_height
        time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

编辑

请使用新的 mouse.wheel(x, y) 功能查看下面的答案,了解使用 playwright 进行滚动的最新方式。将我的答案与他的答案结合起来,以减少使用 JS 的需要。

  • 好的!这也可以调整为使用“scrollTop += 200”慢慢地将页面滚动到末尾,而不是仅仅分配“scrollHeight”。 (2认同)

小智 15

新的剧作家版本具有滚动功能。它被称为mouse.wheel(x, y). 在下面的代码中,我们将尝试滚动浏览具有“无限滚动”的 youtube.com:

from playwright.sync_api import Playwright, sync_playwright
import time


def run(playwright: Playwright) -> None:
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()

    # Open new page
    page = context.new_page()

    page.goto('https://www.youtube.com/')

    # page.mouse.wheel(horizontally, vertically(positive is 
    # scrolling down, negative is scrolling up)
    for i in range(5): #make the range as long as needed
        page.mouse.wheel(0, 15000)
        time.sleep(2)
        
    
    time.sleep(15)
    # ---------------------
    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)
Run Code Online (Sandbox Code Playgroud)


小智 9

其他解决方案对我来说有点冗长和“矫枉过正”,而这对我有用。

这是一个两眼线,让我有些偏头痛才过来:)

注意:您必须输入自己的选择器。这只是一个例子......

    while page.locator("span",has_text="End of results").is_visible() is False:
        page.mouse.wheel(0,100)
        #page.keyboard.down(PageDown) also works
Run Code Online (Sandbox Code Playgroud)

从字面上看,只是继续滚动,直到出现某种独特的选择器。在这种情况下,当您滚动到底部时,会弹出带有字符串“结果结束”(针对我的用例的上下文)的跨度标记。

我相信你可以翻译这个逻辑以供你自己使用。