【问题标题】:Puppeteer can't click on element after page.waitForTimeout called调用 page.waitForTimeout 后,Puppeteer 无法单击元素
【发布时间】:2021-08-12 17:41:20
【问题描述】:

我正在使用 Telegram 机器人和 puppeteer 进行练习,因此我决定创建一个机器人来从特定网站订购披萨。

一旦机器人按照他需要的顺序将他输入的数据放在页面上,如下所示:

这两个字段是 span,当 puppeteer 单击启用的字段(左)时,他会得到一个输入来完成。然后,当第一个输入完成后,puppeteer 必须对第二个字段执行完全相同的过程:单击<span> 标签,将数据放入输入等。

但问题是在第一个字段的完成和第二个字段的激活之间有一个小的时间间隔。我的机器人无法识别这个间隙并立即点击第二个字段的跨度(当然它不起作用)。

这是一个代码片段:

await page.waitForXPath('//*[@id="select2-chosen-2"]', {visible: true})
const [secondSpan] = await page.$x('//*[@id="select2-chosen-2"]')
await secondSpan.click()

当我用这个片段输入node bot 时,我没有收到任何错误或警告。但正如我所说,激活第二个字段需要一些时间。我找到了一个函数可以让 puppeeter 在一段时间内停止执行我的代码:page.waitForTimeout()

这里是 puppeteer 文档中的使用示例:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  page.waitForTimeout(1000).then(() => console.log('Waited a second!'));

  await browser.close();
})();

https://pptr.dev/#?product=Puppeteer&version=v10.1.0&show=api-pagewaitfortimeoutmilliseconds

这是我的情况:

await page.waitForXPath('//*[@id="select2-chosen-2"]', {visible: true})
const [secondSpan] = await page.$x('//*[@id="select2-chosen-2"]')

page.waitForTimeout(1500)

await secondSpan.click()

此代码也没有显示任何错误,但也没有点击该字段。当我将 await 添加到 page.waitForTimeout() 时,我收到此错误:

Error: Node is either not visible or not an HTMLElement

我该如何解决?

【问题讨论】:

  • 你忘记给await你的page.waitForTimeout(1500)打电话了。我不懂俄语,我无法选择启用select2-chosen-2 下拉列表的选项,但最好的方法可能是使用page.waitForFunction 进行轮询,注入您自己的MutationObserverrequestAnimationFrame 循环手动使用evaluate,或者在节点空间中编写一个循环,并在短暂的睡眠中不断检查它是否已启用。如果你能解释我应该给它什么输入以进入下一个选项框,我可以提供答案。
  • 顺便说一句,使用 XPath 作为简单的 id 似乎很愚蠢:'//*[@id="select2-chosen-2"]' 可以是 await page.waitForSelector("#select2-chosen-2"); await page.$("#select2-chosen-2")。或者只是page.click("#select2-chosen-2")
  • @ggorlen 感谢您的回答,我会尽力按照您的建议去做。谈到awaitpage.waitForTimeout,我已经在上一段中描述了这种情况:)
  • @ggorlen 是的,我知道,但这对我来说并不重要,只是想看看 XPAth 是如何工作的
  • 知道了——我想我错过了,但不是awaiting 这没有任何意义,所以这甚至不是一个尝试的选择。最好的情况是它什么都不做,最坏的情况是当您尝试对已关闭的page 执行操作或由于竞争条件导致奇怪的行为时抛出。另一件事是,有时click 会失败,因为 Puppeteer 使用鼠标来执行此操作,但您可以使用 page.evaluate(() => document.querySelector("#select2-chosen-2").click()) 绕过它,这样您就可以点击 Puppeteer 无法找到的元素。

标签: javascript node.js async-await puppeteer telegram-bot


【解决方案1】:

所以我只需要输入这段代码:

await page.click('#s2id_home-number-modal')

或者使用 XPath:

const [secondSpan] = await page.$x('//*[@id="select2-chosen-2"]')
await secondSpan.click()

进入.then() 方法,在page.setTimeout(500) 之后调用。 总而言之,它看起来是这样的(顺便说一下,我已经改变了一些选择器,但这没什么大不了的):

await page.waitForTimeout(500).then(async () => {
   await page.click('#s2id_home-number-modal')
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 2021-02-02
    • 2019-07-03
    • 2018-07-18
    • 1970-01-01
    相关资源
    最近更新 更多