简体   繁体   中英

Puppeteer can't find id

I'm triyng to get my puppeteer to login with my gmail on zalando. Im using the id for the button so it can typ my gmail into it but it just doesn't want to. Can you help me?

This is where the id, class etc is:

<input type="email" class="cDRR43 WOeOAB _0Qm8W1 _7Cm1F9 FxZV-M bsVOrE 
mo6ZnF dUMFv9 K82if3 LyRfpJ pVrzNP NN8L-8 QGmTh2 Vn-7c-" 
id="login.email" data-testid="email_input" name="login.email" value="" 
placeholder="E-postadress" autocomplete="email">

This is my code:

const puppeteer = require('puppeteer');

const product_url = "https://www.zalando.se/nike-sportswear-air-flight-lite-mid-hoega-sneakers-       whiteblack-ni112n02z-a11.html"
const cart = "https://www.zalando.se/cart"



async function givePage(){
    const browser = await puppeteer.launch({headless: false})
    const page = await browser.newPage();
    return page;
}

async function addToCart(page){
    // going to website
    await page.goto(product_url)
    // clicking "handla"
    await page.waitForSelector("button[class='DJxzzA u9KIT8 uEg2FS U_OhzR ZkIJC- Vn-7c- FCIprz heWLCX JIgPn9 LyRfpJ pxpHHp Md_Vex NN8L-8 GTG2H9 MfX1a0 WCjo-q EKabf7 aX2-iv r9BRio mo6ZnF  PLvOOB']");
    await page.click("button[class='DJxzzA u9KIT8 uEg2FS U_OhzR ZkIJC- Vn-7c- FCIprz heWLCX JIgPn9 LyRfpJ pxpHHp Md_Vex NN8L-8 GTG2H9 MfX1a0 WCjo-q EKabf7 aX2-iv r9BRio mo6ZnF  PLvOOB']", elem => elem.click());
    // clicking "OK" to cookies
    await page.waitForSelector("button[class='uc-btn uc-btn-primary']");
    await page.click("button[class='uc-btn uc-btn-primary']", elem => elem.click());
    // clicking "size EU 41"
    await page.evaluate(() => document.getElementsByClassName('_6G4BGa _0Qm8W1 _7Cm1F9 FxZV-M IvnZ13 Pb4Ja8 ibou8b JT3_zV ZkIJC- Md_Vex JCuRr_ na6fBM _0xLoFW FCIprz pVrzNP KRmOLG NuVH8Q')[4].click());
    console.log("körs")
    await page.evaluate(async() => { setTimeout(function(){ console.log('waiting'); }, 1000);});
    // going to "cart"
    await page.goto(cart)
    // clicking "gå till checkout"
    await page.waitForSelector("button[class='z-1-button z-coast-base-primary-accessible z-coast-base__sticky-sumary__cart__button-checkout z-1-button--primary z-1-button--button']");
    await page.click("button[class='z-1-button z-coast-base-primary-accessible z-coast-base__sticky-sumary__cart__button-checkout z-1-button--primary z-1-button--button']", elem => elem.click());
}


async function Login(page){
    await page.evaluate(async() => { setTimeout(function(){ console.log('waiting'); }, 1000);});
    await page.type("input[id='login.email']", 'david.exartor@gmail.com');
}



async function checkout(){
var page = await givePage();
await addToCart(page);
await Login(page);
}

checkout();

I've tried using the other things such as the name, class and testid but still no success. I was expecting that something would work but nothing did.

You're missing waiting for that input selector:

const uname = await page.waitForSelector("[id='login.email']");
await uname.type('david.exartor@gmail.com');

Suggestions/notes:

  • This code:

     await page.click("button[class='uc-btn uc-btn-primary']", elem => elem.click());

    can just be:

     await page.click("button[class='uc-btn uc-btn-primary']");

    The second argument is supposed to be an options object, not a callback. If you want to trigger a native click, use:

     await page.$eval("button[class='uc-btn uc-btn-primary']", el => el.click());
  • When I run into trouble automating a login, I often add a userDataDir and pop open a browser session so I can log in to the site manually.

  • Try to avoid sleeping . It slows down your script and can lead to random failures. Pick tighter predicates like waitForSelector or waitForFunction and encode the exact condition you're waiting on.

    Luckily, your attempts at sleeping don't actually do much of anything:

     await page.evaluate(async() => { setTimeout(function(){ console.log('waiting'); }, 1000);});

    This just logs to the browser console after a second but doesn't block in Puppeteer. The async keyword isn't necessary. To actually sleep in the browser, you could do:

     await page.evaluate(() => new Promise(r => setTimeout(r, 1000)));

    or just sleep in Node:

     await new Promise(r => setTimeout(r, 1000));
  • If you run console.log(await page.content()) headlessly, you'll see the site is detecting you as a bot and not returning the login page. The canonical is Why does headless need to be false for Puppeteer to work? if you plan to run headlessly in the future.

  • The givePage function leaks a browser handle, hanging the process. Better to write your script without abstractions until you have everything working, then factor out abstractions. My usual boilerplate is something like:

     const puppeteer = require("puppeteer"); const scrape = async page => { // write your code here const url = "https://www.example.com"; await page.goto(url, {waitUntil: "domcontentloaded"}); console.log(await page.title()); }; let browser; (async () => { browser = await puppeteer.launch(); const [page] = await browser.pages(); await scrape(page); })().catch(err => console.error(err)).finally(() => browser?.close());
  • Be extremely careful with your [class="foo bar baz"] selectors. These are rigid and overly-precise relative to the preferred .foo.bar.baz version. The former is an exact match, so if another class shows up or the order of the classes change, your script will break. Here's an example of the problem:

     const puppeteer = require("puppeteer"); // ^19.0.0 const html = `<p class="foo bar">OK</p>`; let browser; (async () => { browser = await puppeteer.launch(); const [page] = await browser.pages(); await page.setContent(html); const p = (...args) => console.log(...args); const text = sel => page.$eval(sel, el => el.textContent).catch(err => "FAIL"); // Good: p(await text(".foo.bar")); // => OK p(await text(".bar.foo")); // => OK p(await text(".foo")); // => OK p(await text(".bar")); // => OK // Works but brittle: p(await text('[class="foo bar"]')); // => OK // Special cases that are sometimes necessary: p(await text('[class^="foo "]')); // => OK p(await text('[class$=" bar"]')); // => OK p(await text('[class~="foo"][class~="bar"]')); // => OK // Fails: p(await text('[class="foo"]')); // => FAIL p(await text('[class="bar"]')); // => FAIL p(await text('[class="bar foo"]')); // => FAIL })().catch(err => console.error(err)).finally(() => browser?.close());

    The [attr=""] selector is suitable in uncommon situations when you need to test semantics like "begins with", "ends with", "substring" or in a very rare case where you actually need to distinguish between class="foo bar" and class="bar foo" , which I've never had to do before.

  • Be careful with overly-specific selectors like .foo.bar.baz.quux.garply.corge . If you can distinguish that element with a simple .foo or a #baz.foo , just use that in most circumstances. Related: overusing browser-generated selectors and Convenient way to get input for puppeteer page.click() .

  • Block images and extra resources to speed up your script once you get the basic functionality working.

do you have this error code when you connect to your email befor checking in '''Une erreur est survenue.On recommence plus tard? 18.ddc8645f.1673217035.199ae40'''

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM