如何点击操纵up中的一系列链接?

时间:2019-11-17 22:31:51

标签: javascript 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,但它没有给我上一个执行上下文。

不确定我的猜测是对还是错,并且找不到任何类似的问题,希望我能在这里得到一些帮助,谢谢!

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

1 个答案:

答案 0 :(得分:1)

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}`);
}

尽管有一个内部屏幕快照队列,您甚至可以并行执行此操作。