英文:
button not clickable with puppeteer
问题
我正在尝试自动化登录我的一个账户,但这个网站有一个奇怪的密码表格,我必须点击它才能输入密码,但当我选择表格中的按钮并尝试点击时,我收到以下错误信息:
throw new Error('Node is either not clickable or not an HTMLElement')
引发错误的代码行是:button.click()
以下是代码:
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);
const nextButton = await page.$("#form\\:submit");
await nextButton.click();
await page.waitForSelector(".keypad-key");
const buttons = await page.$$('.keypad-key');
for (let button of buttons) {
let valueHandle = await button.getProperty('textContent');
let btnText = await valueHandle.jsonValue();
if (btnText === "Shift") {
button.click();
}
}
}
test();
英文:
I am trying to automate a login process into one of my accounts and this website has some weird password table that I have to click on to type my password , but when I select a button from the table and try to click on it I get the error:
throw new Error('Node is either not clickable or not an HTMLElement')
the line that is causing the error is : ** button.click()**
here is the code :
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)
const nextButton= await page.$("#form\\:submit")
await nextButton.click()
await page.waitForSelector(".keypad-key")
const buttons = await page.$$('.keypad-key');
for(let button of buttons){
let valueHandle = await button.getProperty('textContent');
let btnText = await valueHandle.jsonValue();
if(btnText==="Shift"){
button.click()
}
}
}
test()
答案1
得分: 1
这一行也导致了你的代码问题:
let btnText = await valueHandle.jsonValue();
你应该将密码拆分成字符,然后循环遍历它,点击与密码中的字符匹配的键盘键。使用XPATH可以获取包含文本的元素,例如//button[contains(@class,"keypad-key") and text()="a"]
选择具有类名keypad-key且文本内容为a的按钮。
代码:
const puppeteer = require('puppeteer');
let browser;
(async () => {
async function login(user, password) {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
async function waitClick(selector) {
let btn = await page.waitForSelector(selector);
await btn.click();
}
let url = 'https://ebanking.cpa-bank.dz/customer/';
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
await page.waitForSelector('#form\\:username'); // 等待页面加载
await page.keyboard.type(user, { delay: 10 });
await waitClick('#form\\:submit'); // 点击下一步
await page.waitForSelector('body'); // 等待页面加载
await waitClick('#inputPassId'); // 先点击输入区域
let passArr = [...password]; // 将密码拆分为字符数组
for (let el of passArr) {
if (/[A-Z]/.test(el)) { // 如果是大写字母,按Shift键
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="${el}"]`);
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="Shift"]`);
} else {
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="${el}"]`);
}
}
await waitClick('#form\\:showPasswordId a'); // 点击显示密码(如果需要)
await waitClick('#form\\:loginButton');
//await browser.close();
}
await login("96391281", "AadBaiudhw");
})().catch(err => console.error(err)).finally(() => browser ?. close());
英文:
This line is also causing the problem in your code,
let btnText = await valueHandle.jsonValue();
You should split the password into characters, then loop through it clicking on the keypad keys that match the characters in the password. Using XPATH you can get elements that contain a text e.g. //button[contains(@class,"keypad-key") and text()="a"]
selects button with class keypad-key, which has text content a
,
Code :
const puppeteer = require('puppeteer');
let browser;
(async () => {
async function login(user, password) {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
async function waitClick(selector) {
let btn = await page.waitForSelector(selector);
await btn.click();
}
let url = 'https://ebanking.cpa-bank.dz/customer/';
await page.goto(url, {waitUntil: 'networkidle2', timeout: 30000});
await page.waitForSelector('#form\\:username'); // wait for page
await page.keyboard.type(user, { delay: 10 });
await waitClick('#form\\:submit'); // click next
await page.waitForSelector('body'); // wait for page
await waitClick('#inputPassId'); // click on input area first
let passArr = [...password]; // split password into array of characters
for(let el of passArr) {
if (/[A-Z]/.test(el)) { //press shift if uppercase
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="Shift"]`);
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="${el}"]`);
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="Shift"]`);
} else {
await waitClick("xpath/" + `//button[contains(@class,"keypad-key") and text()="${el}"]`);
}
}
await waitClick('#form\\:showPasswordId a'); // click to show password not required
await waitClick('#form\\:loginButton');
//await browser.close();
}
await login("96391281", "AadBaiudhw" );
})().catch(err => console.error(err)).finally(() => browser ?. close());
答案2
得分: 0
从快速查看情况来看,Puppeteer可能无法通过网站对该按钮进行的所有必要检查,安全性可能超出了Puppeteer的复杂性,导致Puppeteer抛出默认错误。
显然,Puppeteer必须以编程方式生成这些点击,以满足它们认为需要点击按钮的条件。解决这个问题的方法可以是,要么不使用Puppeteer来执行这些操作,要么读取按钮事件监听器上的代码,查看它正在检查什么,然后将其与Puppeteer如何触发伪造点击进行比较。
英文:
From a quick glance of the situation, puppeteer just might not pass all the necessary checks that the website has on that button, the security might be past the complexity of puppeteer which is causing puppeteer to throw a default error.
Obviously puppeteer has to programmatically generate those clicks to what they think will be needed to click buttons, a solution to this would be to either do this without puppeteer or to read the code on the button event listener and see what it is checking for and then compare that to how puppeteer is dispatching their spoofed clicks.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论