如何在puppeteer中点击一系列链接



我是木偶师的新手,试图通过编写一个简单的抓取作业来了解它是如何工作的。

我计划做什么

计划很简单:

  1. 转到一个页面
  2. 则提取一个CCD_ 2标签下的所有CCD_
  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}`);
}

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

最新更新