如何使用Puppeteer抓取嵌套IFrame内的网页数据?
解决Puppeteer抓取嵌套IFrame内数据的问题
你的代码只处理了第一层IFrame,但目标数据实际在第二层嵌套IFrame里,所以无法获取到内容。同时硬编码的等待时间和XPath定位容易受页面结构变动影响,需要调整为更可靠的处理方式,具体解决方案如下:
核心问题分析
- 点击菜单后加载的页面中,第一层IFrame内部还嵌套了第二层IFrame,目标表格就在第二层IFrame里
- 依赖固定时间的
waitForTimeout不稳定,应该用元素加载等待替代 - 基于绝对路径的XPath定位容错性差,建议结合文本内容定位目标行
修改后的代码
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: false }); // 开启headless:false可方便调试 const page = await browser.newPage(); // 等待页面网络请求稳定后再继续 await page.goto('https://www.saisp.br/online/produtos-publicos/', { waitUntil: 'networkidle2' }); // 点击左侧菜单"Paraíba do Sul Telemetric Network" await page.waitForXPath('/html/body/app-home/div/nav/ul/li[12]/div/div[1]/a'); const [menuLink] = await page.$x('/html/body/app-home/div/nav/ul/li[12]/div/div[1]/a'); await menuLink.click(); // 切换到第一层IFrame上下文 await page.waitForSelector('iframe'); const [outerIframe] = await page.$x('/html/body/app-home/div/main/iframe'); const outerFrame = await outerIframe.contentFrame(); // 切换到第二层嵌套IFrame上下文 await outerFrame.waitForSelector('iframe'); const [innerIframe] = await outerFrame.$x('//iframe'); const innerFrame = await innerIframe.contentFrame(); // 等待目标表格加载完成 await innerFrame.waitForSelector('#tbTelemBody'); // 通过文本内容定位目标行的第二个单元格 const [targetCell] = await innerFrame.$x("//td[contains(text(), 'Rio Paraitinga - Passarela / São Luiz do Paraitinga')]/following-sibling::td[1]"); const cellValue = await innerFrame.evaluate(el => el.textContent.trim(), targetCell); console.log('目标数据:', cellValue); await browser.close(); })();
关键调整说明
- 逐层切换IFrame上下文:先进入外层IFrame,再在该IFrame内找到内层IFrame并切换上下文,确保能访问到嵌套的内容
- 替换硬等待:用
waitForXPath、waitForSelector和networkidle2等待策略,确保元素或页面完全加载后再执行操作 - 精准定位目标行:通过
contains(text())的XPath匹配目标行的名称,再定位其相邻的单元格,避免依赖固定的行/列索引,提升代码稳定性
内容的提问来源于stack exchange,提问作者dihslp
相关产品推荐
相关产品推荐

