Puppeteer page.goTo() 永远不会完成

sim*_*w16 6 javascript automation node.js e2e-testing puppeteer

为什么 puppeteer page.goto() 挂起?

这是发生这种情况的另一个例子^

我一直不明白为什么,但即使是最简单的木偶脚本也无法通过 goTo()

我有以下代码:

    const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome-unstable', args: ["--proxy-server='direct://'", '--proxy-bypass-list=*', '--no-sandbox', '--disable-setuid-sandbox'] });
    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36');
    await page.setDefaultNavigationTimeout(0);

    log('before nav');
    await page.goto('http://www.google.com');

    log('waiting nav');
    await page.waitForNavigation({
        waitUntil: 'networkidle0'
    });

    log('complete');

    await browser.close();
Run Code Online (Sandbox Code Playgroud)

输出是:

$:# node lib/tests/nav.test.js
    before nav
    waiting nav

Run Code Online (Sandbox Code Playgroud)

它永远不会记录“完整”。我尝试过不使用代理旁路和代理服务器、打开和关闭无沙箱。我努力了networkidle2。它没有完成。我还尝试了各种不同的网站。我使用 Puppeteer 4.x 并使用节点 12.x 和 npm 6.x。

我研究了人们建议的 Promise 方法:

await Promise.All([ page.goto('http://www.google.com'), page.waitForNavigation() ]);
Run Code Online (Sandbox Code Playgroud)

这有时有效。但这种情况非常零星。

傀儡师真的有这么烂吗?是否有任何已知的方法可以在执行操作之前保证页面加载。我需要四处导航并填写表格并单击按钮等,因此所有元素都需要在那里。

我也尝试了该waitForSelector()版本,也无法加载。

我觉得傀儡师已经从根本上崩溃了。有任何想法吗?

pav*_*man 10

您没有按照应有的方式使用 Puppeteer,这就是为什么它感觉有问题,但这主要是因为您不知道脚本中发生了什么。

我们来看一下。

await page.goto('http://www.google.com');
Run Code Online (Sandbox Code Playgroud)

这实际上意味着:

await page.goto('http://www.google.com', { waitUntil: 'load' });
Run Code Online (Sandbox Code Playgroud)

因此,您将转到一个页面并等待加载事件触发。这意味着当您到达该线后面时,无需等待其他导航。因此这一行:

await page.waitForNavigation();
Run Code Online (Sandbox Code Playgroud)

将永远等待。这就是您所描述的“它挂起”。

因此,由于该方法page.goTo()已经提供了指定导航何时成功的方法(当前它们是:load、domcontentloaded、networkidle0、networkidle2),因此您实际上不需要结合使用任何其他方法page.goTo()

另一种情况是,当您单击按钮并期望发生某些事情时,例如页面中出现导航或选择器。由于该方法page.click()不提供与 相同的选项page.goTo(),因此您通常需要组合使用另一种方法,如下所示:

await Promise.all([
    page.waitForNavigation(),
    page.click(selector)
]);
Run Code Online (Sandbox Code Playgroud)

或者等待导航和一些选择器:

await Promise.all([
    page.waitForNavigation({ waitUntil: 'networkidle0' }),
    page.waitForSelector(selector),
    fbButton.click()
]);
Run Code Online (Sandbox Code Playgroud)

如果您坚持这些模式,我认为您不会觉得 Puppeteer 有问题。只是它是一个低级工具,因此您需要编写比 WebdriverIO 等其他框架更多的代码。