
在使用puppeteer进行自动化测试时,处理动态密码键盘这类非标准输入组件常遇到点击失效问题,表现为`node is either not clickable or not an htmlelement`错误。本教程将详细介绍如何通过将密码拆分为字符、利用xpath精确匹配键盘按键,并结合shift键处理大小写,从而有效解决此类复杂ui元素的交互挑战,确保自动化流程的稳定执行。
在许多银行或安全敏感的网站中,为了提高安全性,会采用动态密码键盘(虚拟键盘)来代替传统的文本输入框。这种键盘的按键通常是动态渲染的HTML元素,它们的ID可能不固定,或者在页面加载后才出现。当尝试使用Puppeteer直接选择并点击这些元素时,可能会遇到以下问题:
为了克服这些挑战,我们需要一种更精确、更健壮的元素选择和交互策略。
核心解决方案在于结合以下策略:
首先,确保您的项目中已安装Puppeteer。
const puppeteer = require('puppeteer');为了提高代码的可读性和复用性,我们可以创建一个辅助函数来封装“等待元素并点击”的常见操作。
// 辅助函数:等待元素出现并点击
async function waitClick(page, selector, isXPath = false) {
let btn;
if (isXPath) {
// 使用page.waitForXPath等待XPath元素
btn = await page.waitForXPath(selector, { visible: true, timeout: 5000 });
// Puppeteer的XPath结果是ElementHandle数组,需要取第一个
await btn.click();
} else {
// 使用page.waitForSelector等待CSS选择器元素
btn = await page.waitForSelector(selector, { visible: true, timeout: 5000 });
await btn.click();
}
}注意: 当使用XPath时,page.waitForXPath返回的是ElementHandle的数组,但click()方法通常直接作用于单个ElementHandle。如果XPath预期只匹配一个元素,可以直接在返回的ElementHandle上调用click()。如果waitClick函数需要通用,可以考虑page.waitForXPath返回的ElementHandle数组的第一个元素,或者直接使用page.click(selector)如果selector是XPath字符串且page.click支持。在上述修改后的waitClick中,为了简化,假设page.waitForXPath返回的btn是可直接点击的ElementHandle(这通常是正确的行为)。
以下是完整的自动化登录函数,它将处理用户名输入、密码键盘交互和最终的登录提交。
const puppeteer = require('puppeteer');
// 辅助函数:等待元素出现并点击
async function waitClick(page, selector, isXPath = false) {
let elementHandle;
try {
if (isXPath) {
// 使用page.waitForXPath等待XPath元素,并确保可见
const elements = await page.waitForXPath(selector, { visible: true, timeout: 10000 });
// 如果XPath返回多个元素,通常我们希望点击第一个匹配项
if (Array.isArray(elements) && elements.length > 0) {
elementHandle = elements[0];
} else {
throw new Error(`XPath selector "${selector}" did not find any visible elements.`);
}
} else {
// 使用page.waitForSelector等待CSS选择器元素,并确保可见
elementHandle = await page.waitForSelector(selector, { visible: true, timeout: 10000 });
}
await elementHandle.click();
} catch (error) {
console.error(`Error clicking element with selector "${selector}" (isXPath: ${isXPath}):`, error);
throw error; // 重新抛出错误以便上层捕获
}
}
async function login(user, password) {
let browser;
try {
browser = await puppeteer.launch({ headless: false, defaultViewport: null }); // 设置headless: false便于观察,defaultViewport: null防止默认视口裁剪
const page = await browser.newPage();
const url = 'https://ebanking.cpa-bank.dz/customer/';
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 }); // 等待网络空闲,确保页面完全加载
// 1. 输入用户名
await page.waitForSelector('#form\:username', { visible: true }); // 等待用户名输入框出现
await page.type('#form\:username', user, { delay: 50 }); // 模拟人类输入,增加延迟
// 2. 点击“下一步”或提交按钮
await waitClick(page, '#form\:submit');
// 3. 等待密码键盘区域加载
await page.waitForSelector('body', { visible: true }); // 等待页面体加载完毕
await waitClick(page, '#inputPassId'); // 点击密码输入区域,激活键盘
// 4. 处理密码输入
const passArr = [...password]; // 将密码字符串拆分为字符数组
for (const char of passArr) {
if (/[A-Z]/.test(char)) { // 如果字符是大写字母
// 模拟按下Shift键
await waitClick(page, "xpath/" + `//button[contains(@class,"keypad-key") and text()="Shift"]`, true);
// 点击大写字母
await waitClick(page, "xpath/" + `//button[contains(@class,"keypad-key") and text()="${char}"]`, true);
// 模拟释放Shift键
await waitClick(page, "xpath/" + `//button[contains(@class,"keypad-key") and text()="Shift"]`, true);
} else {
// 点击普通字符
await waitClick(page, "xpath/" + `//button[contains(@class,"keypad-key") and text()="${char}"]`, true);
}
}
// 5. 点击登录按钮 (根据实际页面调整选择器)
// 示例中有一个显示密码的按钮,可能不需要点击,直接点击登录
// await waitClick(page, '#form\:showPasswordId a'); // 如果有显示密码按钮,可能需要点击或跳过
await waitClick(page, '#form\:loginButton'); // 点击最终的登录按钮
console.log('登录流程执行完毕。');
// 可以在这里添加一些断言来验证登录是否成功
// 例如:await page.waitForSelector('.dashboard-element');
} catch (error) {
console.error('登录过程中发生错误:', error);
throw error; // 重新抛出错误,方便外部调用者处理
} finally {
if (browser) {
// await browser.close(); // 登录成功或失败后关闭浏览器
}
}
}
// 执行登录函数
(async () => {
try {
await login("96391281", "AadBaiudhw");
} catch (error) {
console.error('主程序捕获到错误:', error);
}
})();
通过本教程,我们学习了如何使用Puppeteer有效处理动态密码键盘的自动化点击问题。关键在于:将复杂的输入分解为字符级操作,利用XPath进行精确且稳定的元素定位,并妥善处理特殊按键(如Shift)。这种方法不仅解决了Node is either not clickable or not an HTMLElement错误,也为自动化其他复杂的、非标准的用户界面元素提供了通用的策略。在实际应用中,务必根据目标网站的具体DOM结构调整CSS选择器和XPath表达式,并利用headless: false进行充分的调试。
以上就是Puppeteer自动化:处理动态密码键盘点击与XPath策略的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号