Puppeteer表格分页问题:Next按钮仅触发一次点击操作
Puppeteer分页点击仅触发一次的问题解决
问题描述
使用Puppeteer实现表格多页导航时,循环点击「Next」按钮切换分页,count变量显示循环迭代次数正确,但点击事件仅触发一次,后续点击无效。
原代码
import puppeteer from "puppeteer"; export const getNigeriaPortsLineups = async () => { let browser; try { browser = await puppeteer.launch({ ignoreHTTPSErrors: true, headless: false, timeout: 60000, }); const width = 1920, height = 1080; const page = await browser.newPage(); await page.setViewport({ width, height }); await page.setUserAgent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36" ); await page.goto("https://shippos.nigerianports.gov.ng/", { timeout: 60000, }); await page.evaluate(async () => { let nextButton = document.querySelector("#Apapa2_next") as HTMLElement; const tableRows = document.querySelectorAll("#Apapa2 tbody tr"); const sugarRows = Array.from(tableRows).map((row) => { return Array.from(row.querySelectorAll("td")).map((cell) => cell.textContent.trim() ); }); let count = 0; while (count <= 4) { console.log(count); await new Promise((resolve) => setTimeout(resolve, 2000)); nextButton.click() count++; } // while (nextButton && !nextButton.classList.contains("disabled")) { // nextButton.click(); // await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for a second before clicking again // } }); } catch (error) { console.error(error); } finally { // if (browser) await browser.close(); } };
问题原因
- DOM元素引用失效:一开始获取的
nextButton是第一页的元素,分页切换后页面会重新渲染分页控件,原按钮元素已被移除,后续点击的是失效的DOM引用,自然无反应。 - 未确保页面更新完成:单纯用
setTimeout等待,无法保证新分页元素加载完成,即使重新获取按钮也可能拿到未更新的元素。
修复后的代码
import puppeteer from "puppeteer"; export const getNigeriaPortsLineups = async () => { let browser; try { browser = await puppeteer.launch({ ignoreHTTPSErrors: true, headless: false, timeout: 60000, }); const width = 1920, height = 1080; const page = await browser.newPage(); await page.setViewport({ width, height }); await page.setUserAgent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36" ); await page.goto("https://shippos.nigerianports.gov.ng/", { timeout: 60000, waitUntil: "networkidle2" // 确保页面初始加载完成 }); // 收集所有页面的数据 const allRows = []; let count = 0; const maxPages = 4; // 最多翻4页 while (count <= maxPages) { // 获取当前页表格数据 const currentRows = await page.evaluate(() => { const tableRows = document.querySelectorAll("#Apapa2 tbody tr"); return Array.from(tableRows).map(row => Array.from(row.querySelectorAll("td")).map(cell => cell.textContent.trim()) ); }); allRows.push(...currentRows); try { // 等待下一页按钮存在且未禁用 await page.waitForSelector("#Apapa2_next:not(.disabled)", { timeout: 5000 }); // 点击按钮(Puppeteer会自动等待元素可交互) await page.click("#Apapa2_next"); // 等待表格内容更新,确保分页切换完成 await page.waitForFunction( (prevRowCount) => document.querySelectorAll("#Apapa2 tbody tr").length !== prevRowCount, {}, currentRows.length ); } catch (err) { // 无下一页时退出循环 break; } count++; } console.log("所有页面数据:", allRows); } catch (error) { console.error(error); } finally { if (browser) await browser.close(); } };
关键修复点
- 放弃缓存按钮引用:使用
page.waitForSelector和page.click,每次操作都重新查找按钮,自动适配DOM更新后的元素。 - 等待元素可交互:
page.click会自动等待元素处于可点击状态,比直接调用DOM的click方法更可靠。 - 监听页面内容变化:用
page.waitForFunction监听表格行数变化,确保分页切换完成后再进行下一次操作,替代固定时长的setTimeout。 - 完整收集数据:修复原代码仅获取第一页数据的问题,循环中收集每一页的表格内容。
内容的提问来源于stack exchange,提问作者user12504353
相关产品推荐
相关产品推荐

