javascript - 如何单击 puppeteer 中的一系列链接?

标签 javascript node.js puppeteer

我是 puppeteer 的新手,试图通过编写一个简单的抓取作业来了解它的工作原理。

我打算做什么

计划很简单:

  1. 转到一个页面,
  2. 然后提取所有<li> <ul> 下的链接标签
  3. 单击每个 <li>链接并截取目标页面的屏幕截图。

我是如何实现的

代码如下,

  await page.goto('http://some.url.com');                 // step-1
  const a_elems = await page.$$('li.some_css_class a');   // step-2

  for (var i=0; i<a_elems.length; i++) {                  // step-3
    const elem = a_elems[i];
    await Promise.all([
      elem.click(),
      page.waitForNavigation({waitUntil: 'networkidle0'})   // click each link and wait page loading
    ]);
    await page.screenshot({path: `${IMG_FOLDER}/${txt}.png`});

    await page.goBack({waitUntil: 'networkidle0'});      // go back to previous page so that we could click next link
    console.log(`clicked link = ${txt}`);
  }

出了什么问题,需要帮助

然而,上面的代码只能处理a_elems中的第一个链接。 ,当 for-loop来到第二个链接,代码中断并显示错误

(node:40606) UnhandledPromiseRejectionWarning: Error: Node is detached from document
    at ElementHandle._scrollIntoViewIfNeeded (.../.npm-packages/lib/node_modules/puppeteer/lib/JSHandle.js:203:13)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async ElementHandle.click (.../.npm-packages/lib/node_modules/puppeteer/lib/JSHandle.js:282:5)
    at async Promise.all (index 0)
    at async main (.../test.js:34:5)
  -- ASYNC --
    at ElementHandle.<anonymous> (.../.npm-packages/lib/node_modules/puppeteer/lib/helper.js:111:15)
    at main (.../test.js:35:12)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

我怀疑 page 的执行上下文单击第一个链接后已经更改,即使我调用了 page.goBack到上一页,但它没有给我以前的执行上下文。

不确定我的猜测是否正确,也没有找到类似的问题,希望能得到一些帮助,谢谢!

如果有更好的实现方式来实现我的计划,请告诉我。

最佳答案

当您 goBack 时,您认为元素会丢失其上下文是正确的。那是行不通的。
但是,正如您评论的那样,您可以从元素中获取 href 并从那里开始:


for (var i=0; i<a_elems.length; i++) {                  // step-3
  const elem = a_elems[i];
  const href = await page.evaluate(e => e.href, elem); //Chrome will return the absolute URL
  const newPage = await browser.newPage();
  await newPage.goto(href);
  await newPage.screenshot({path: `${IMG_FOLDER}/${txt}.png`});
  await newPage.close();
  console.log(`clicked link = ${txt}`);
}

您甚至可以并行执行此操作,尽管有一个用于屏幕截图的内部队列。

关于javascript - 如何单击 puppeteer 中的一系列链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58905844/

相关文章:

javascript - 在另一个函数内调用函数 - Uncaught Error

javascript - 无法与无框架的透明BrowserWindow进行交互

node.js - nestjs中模块之间的循环依赖

javascript - 在这里正确使用函数式编程 : how do I use . map() 有效吗?

Javascript Jquery 在外部样式表更改/重新加载 promise 方式后执行代码

html - 获取 Angular js 中返回的 JSON 对象的值

python - Moongoose 和 dict 转换为数组失败

node.js - Puppeteer-Cluster 的隐秘性是否足以通过机器人测试?

javascript - 如何在 Puppeteer 中截取屏幕截图或 PDF 之前删除标签?

javascript - 如何将 Puppeteer 与 Stripe 元素结合使用