使用Puppeteer自动化登录时点击按钮报错:Node不可点击或非HTMLElement
解决Puppeteer点击密码键盘按钮报错的问题
问题根源
报错Node is either not clickable or not an HTMLElement通常由以下原因导致:
page.waitForSelector('.keypad-key')仅等待元素存在,但元素可能还未处于可见、可交互状态- 提前获取的元素句柄(
$$返回的数组)可能因页面动态更新失效 - 元素可能被遮挡、不在视口内,直接调用
button.click()无法触发交互
修复方案及代码示例
1. 等待元素完全可交互
将基础的元素存在等待,替换为等待元素可见且可点击:
await page.waitForSelector('.keypad-key', { visible: true, timeout: 10000 });
2. 避免元素句柄失效,改用页面上下文定位
不要提前缓存所有按钮句柄,而是每次通过文本直接定位目标按钮,确保操作时元素状态有效:
const puppeteer = require("puppeteer"); function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const pwd = ["123456", "dadhaiudhw", "3712893jdhusydiu", "12kd9", "12!@#@4dmsak"]; const test = async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto("https://ebanking.cpa-bank.dz/customer/"); // 输入用户名(注意转义选择器中的冒号) const inputElement = await page.$('#form\\:username'); await inputElement.type("96391281", { delay: 100 }); await sleep(Math.random() * 4200); // 点击下一步,同时等待页面跳转完成 await Promise.all([ page.click("#form\\:submit"), page.waitForNavigation({ waitUntil: 'networkidle2' }) ]); // 等待密码键盘按钮可见且可交互 await page.waitForSelector('.keypad-key', { visible: true, timeout: 10000 }); // 点击Shift按钮(在页面上下文内定位,避免句柄失效) await page.evaluate(() => { const shiftBtn = Array.from(document.querySelectorAll('.keypad-key')) .find(btn => btn.textContent.trim() === "Shift"); if (shiftBtn) shiftBtn.click(); }); // 示例:输入第一个密码 const targetPwd = pwd[0]; for (const char of targetPwd) { // 每次循环重新定位对应字符的按钮 await page.waitForSelector(`.keypad-key:has-text("${char}")`, { visible: true }); await page.click(`.keypad-key:has-text("${char}")`); await sleep(Math.random() * 500); // 模拟人工点击间隔,规避反爬 } // 后续操作:比如提交登录等 // await browser.close(); }; test();
3. 额外注意事项
- 选择器中的特殊字符(如冒号
:)需要用\\:转义 - 点击页面跳转类按钮时,用
Promise.all同时执行点击和等待导航,确保页面状态稳定 - 增加随机延迟模拟人工操作,降低被反爬机制拦截的概率
内容的提问来源于stack exchange,提问作者w4ss
相关产品推荐
相关产品推荐

