如何加快木偶戏?

时间:2020-07-11 17:34:28

标签: javascript node.js puppeteer

网页上有一个按钮,操纵up的人必须尽快单击该按钮。此按钮并不总是可见的,并且同时对每个人都可见。因此,我必须不断刷新以发现该按钮变得可见。我为此编写了以下脚本:

    const browser = await puppeteer.launch({
        headless: true,
        args: ['--no-sandbox']
    });
    const page = await browser.newPage()
    await page.setViewport({ width: 1920, height: 1080})


//I am calling my pageRefresher method here

async function pageRefresher(page,browser, url) {
        try {
            await page.goto(url, {waitUntil: 'networkidle2'})
            try {
                await page.waitForSelector('#ourButton', {timeout: 10});
                await page.click('#ourButton')
                console.log(`clicked!`)
                await browser.close()
            } catch (error) {
                console.log('catch2 ' + counter + ' '  + error)
                counter += 1
                await pageRefresher(page, browser, url)
            }
        }catch (error) {
            console.log('catch3' + error)
            await browser.close();
        }
}

如您所见,我的方法是递归的。它会转到该页面并寻找该按钮。如果没有按钮,则它将再次调用自身以重做相同的作业,直到找到并单击该按钮为止。

实际上,它现在运行良好。但这很慢。我正在运行此脚本,与此同时,我正在桌面chrome上打开同一页面,并且开始手动刷新该页面。而且我总是赢,我总是在操纵up之前单击该按钮。

我如何加快此过程?脚本不应该输给只有F5按钮之类的手动控件的人。

2 个答案:

答案 0 :(得分:4)

脚本不应输给只有F5按钮等手动控件的人。

之所以会发生这种情况,是因为有时伪造者遵循的规则比我们认为的“完全加载的网页”要严格得多。即使您作为一个人也可以决定所需的元素是否已经在DOM中(因为您看到该元素在其中)或该元素不在其中(因为您没有看到它)。例如:即使背景图片仍在后台加载,或者仍然没有加载Web字体并且您具有后备字体,您仍会看到按钮不存在,但是puppeteer在后台等待特定事件以获得许可要么转到catch块(超时),要么获取所需的元素(waitForSelector成功)。它确实取决于您所访问的站点,但是您可以加快识别所需元素的过程。

我提供一些示例和想法,您可以如何实现这一目标。


加快识别所需元素的方法

1。)如果您不需要所有网络连接来完成任务,则可以通过将waitUntil: 'networkidle2'替换为waitUntil: 'domcontentloaded'来加快页面加载速度,因为该事件通常发生在更早的时刻,并且会在{{ 1}}将已经存在于DOM中。

#ourButton / page.goto的可能选项:

  • page.reload-考虑触发load事件时导航完成。
  • load-考虑触发domcontentloaded事件时导航完成。
  • DOMContentLoaded-至少有networkidle0毫秒的网络连接不超过0个时,请考虑完成导航。
  • 500-至少有networkidle2毫秒的网络连接不超过2个时,请考虑完成导航。

您因为500太严格而赢得了脚本。您可能需要此选项(例如,您正在访问单页应用程序,或者稍后您将需要来自第三方网络连接的数据(例如Cookie)),但是如果不是强制性的,则使用networkidle2会获得更好的性能。 / p>

2。)您可以循环使用page.reload方法,而不是不断导航到相同的url,例如:

domcontentloaded

它的主要好处是您可以缩短和简化await page.goto(url, { waitUntil: 'domcontentloaded' }) let selectorExists = await page.$('#ourButton') while (selectorExists === null) { await page.reload({ waitUntil: 'domcontentloaded' }) console.log('reload') selectorExists = await page.$('#ourButton') } await page.click('#ourButton') // code goes on... 函数。但是我的表现也更好(但是我没有进行基准测试,但是感觉比重新打开页面要快得多。)

3。)如果不需要执行任务的每种资源类型,还可以通过使用以下脚本禁用图像或CSS来加快页面加载速度:

pageRefresher

[source]

List of resourceType-s。

答案 1 :(得分:2)

尝试不等待goto:

page.goto(url) // no await because it doesn't have to resolve fully
await page.waitForSelector('#ourButton') // await this because we need it to be there

有些人喜欢Promise.race,但是这种方式更简单