“button not clickable with puppeteer” 可翻译为 “使用 Puppeteer 时按钮无法点击”。

huangapple go评论82阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年6月12日 20:09:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76456537.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定