无法使用 Puppeteer 输入字段

Unable to type into an input field with Puppeteer

我正在尝试使用 Puppeteer 在输入字段中输入文本。

async function reddit() {
  const broswer = await puppeteer.launch({
    headless: false
  })
  const page = await broswer.newPage();
  const navPromise = page.waitForNavigation({
    waitUntil: 'domcontentloaded'
  })

  await page.goto('https://www.reddit.com/r/place/?cx=352&cy=522&px=69')
  await navPromise;
  console.log('did i get this far? 1');
  await page.click('a._3Wg53T10KuuPmyWOMWsY2F:nth-child(2)')
  await navPromise;

  console.log('did i get this far?2 ');
  await page.keyboard.type('#loginUsername', 'hjello')

  console.log('did i get this far?3');
}

reddit()

我在运行时获得了所有三个控制台日志。我可以看到它单击用户名登录,但没有输入任何内容。我查看了多个 Whosebug 问题并尝试了答案,但其中 none 将输入输入。

await page.click('a._3Wg53T10KuuPmyWOMWsY2F:nth-child(2)') 触发 DOM 更改,但随后立即在可能尚未准备好的元素上触发 .click(),因此这看起来像是竞争条件。我建议使用 waitForSelector(如果导航被触发,则使用 waitForNavigation,这里似乎不是这种情况)。

const navPromise = page.waitForNavigation({waitUntil: 'domcontentloaded'}) 位于已经等待导航的 goto 上方的一个奇怪位置,然后 awaited 两次,这没有意义。一旦一个承诺被解决,它就永远不会再被解决,所以你唯一想要这样做的时候是你需要再次访问已解决的值,这在这里不适用。等待额外的导航可能会在未触发时导致超时。

不过,主要问题似乎是您尝试输入的选择器位于 iframe 中。 是可能的,但直接导航到登录页面框架 URL 更容易,然后使用 goto 导航到您所在的任何页面试图到达。

例如:

const puppeteer = require("puppeteer"); // ^13.5.1

let browser;
(async () => {
  browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages();
  const url = "https://www.reddit.com/login/";
  await page.goto(url, {waitUntil: "domcontentloaded"});
  await page.waitForSelector("#loginUsername");
  await page.type("#loginUsername", "hjello");
  await page.type("#loginPassword", "foobar");
  await Promise.all([
    page.waitForNavigation(),
    page.click(".AnimatedForm__submitButton"),
  ]);
  // navigate to wherever you want with page.goto
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

请注意,当您在浏览器控制台中手动选择元素以准备脚本时,document.querySelector 和类似功能可能会在框架上运行,因为在控制台中聚焦时框架会变为活动状态,但从脚本的角度来看,情况并非如此,这会导致很多潜在的混乱。