You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer循环点击提取数据异常:仅点首个按钮且报节点脱离错误

Puppeteer循环点击按钮报错「Node is detached from document」的解决办法

问题根源

你预先获取的viewDetails_btns是初始DOM的元素集合,当点击按钮触发页面跳转或DOM重渲染后,原来的元素节点会脱离当前文档树,第二次循环访问viewDetails_btns[i]时就会抛出「Node is detached from document」错误。另外,循环内重复调用waitForSelector(".docBox span.redColorLink")属于无效操作,还可能干扰元素定位。

解决方案

  • 不要提前缓存按钮列表,每次循环前重新获取最新的按钮元素,确保节点处于当前文档树中
  • 替换固定时长的waitForTimeout为等待特定DOM状态,提升脚本稳定性
  • 返回列表页后,等待页面重新渲染完成再进入下一次循环

修改后的代码

const btnSelector = ".docBox span.redColorLink";
// 先获取总按钮数量,避免循环内重复计算
const totalBtns = await page.$$eval(btnSelector, btns => btns.length);

for (let i = 0; i < totalBtns; i++) {
  console.log("总医生数: ", totalBtns);
  console.log("当前索引: ", i);

  // 每次循环重新获取按钮列表,保证元素是当前DOM的有效节点
  const viewDetailsBtns = await page.$$(btnSelector);
  await viewDetailsBtns[i].click();

  // 等待详情页目标元素加载完成
  await page.waitForSelector("b.ng-tns-c12-0");
  // 直接用$eval提取文本,简化代码逻辑
  const detailText = await page.$eval("b.ng-tns-c12-0", el => el.innerText);
  console.log(detailText);

  // 点击返回按钮回到列表页
  await page.waitForSelector("button.btn");
  await page.click("button.btn");

  // 等待列表页重新渲染完成,确保下一次循环能正确获取按钮
  await page.waitForSelector(btnSelector);
}

关键改动说明

  1. 用$$eval一次性获取总按钮数,避免循环内重复查询DOM
  2. 每次循环重新调用page.$$(btnSelector)获取按钮,彻底解决节点脱离问题
  3. 用$eval合并元素获取与文本提取的逻辑,减少冗余代码
  4. 去掉固定3秒等待,改用等待列表页按钮重新出现,让脚本适配不同加载速度的页面

内容的提问来源于stack exchange,提问作者Basseloob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:12:42