-2

I am trying to make a bot, and I need to select a size. For now, i'm just going to select 11. How would I do this, since all of the buttons have the same class?

I have tried to select the data-testid, but i'm pretty new at puppeteer and node.js in general, so it's been a little hard.

const pt = require('puppeteer')

const url = 'https://stockx.com/buy/air-jordan-1-retro-high-og-chicago-reimagined-lost-and-found'

async function initBrowser(){
    const browser = await pt.launch({headless:false, defaultViewport: null, slowMo:10});
    const page = await browser.newPage();
    await page.goto(url,{waitUntil: 'networkidle0'});
    return page;
}

async function selectSize(){
    const page = await initBrowser();
    await page.$eval("div[data-testid='size-11'" , form => form.click() );
}

async function checkout(){
    await selectSize();
    await page.setViewport({width: 1920, height: 1080})
    await page.screenshot({path: 'test.png'})
}

checkout();

What ends up happening is this:

Error: Error: failed to find element matching selector "div[data-testid="#size-11"]"
    at CDPElementHandle.$eval (*filepath*)
    at async selectSize (*filepath*)
    at async checkout (*filepath*)

Edit: Here's the HTML:

<div title="" class="css-4tso23"><div data-component="grid-tile" data-testid="size-3.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 3.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$270</p></div></div></div><div data-component="grid-tile" data-testid="size-4" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 4</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$252</p></div></div></div><div data-component="grid-tile" data-testid="size-4.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 4.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$293</p></div></div></div><div data-component="grid-tile" data-testid="size-5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$305</p></div></div></div><div data-component="grid-tile" data-testid="size-5.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 5.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$346</p></div></div></div><div data-component="grid-tile" data-testid="size-6" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 6</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$330</p></div></div></div><div data-component="grid-tile" data-testid="size-6.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 6.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$329</p></div></div></div><div data-component="grid-tile" data-testid="size-7" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 7</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$340</p></div></div></div><div data-component="grid-tile" data-testid="size-7.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 7.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$381</p></div></div></div><div data-component="grid-tile" data-testid="size-8" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 8</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$370</p></div></div></div><div data-component="grid-tile" data-testid="size-8.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 8.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$379</p></div></div></div><div data-component="grid-tile" data-testid="size-9" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 9</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$401</p></div></div></div><div data-component="grid-tile" data-testid="size-9.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 9.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$424</p></div></div></div><div data-component="grid-tile" data-testid="size-10" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 10</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$434</p></div></div></div><div data-component="grid-tile" data-testid="size-10.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 10.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$441</p></div></div></div><div data-component="grid-tile" data-testid="size-11" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 11</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$453</p></div></div></div><div data-component="grid-tile" data-testid="size-11.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 11.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$449</p></div></div></div><div data-component="grid-tile" data-testid="size-12" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 12</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$465</p></div></div></div><div data-component="grid-tile" data-testid="size-12.5" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 12.5</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$469</p></div></div></div><div data-component="grid-tile" data-testid="size-13" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 13</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$464</p></div></div></div><div data-component="grid-tile" data-testid="size-14" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 14</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$457</p></div></div></div><div data-component="grid-tile" data-testid="size-15" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 15</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$439</p></div></div></div><div data-component="grid-tile" data-testid="size-16" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 16</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$359</p></div></div></div><div data-component="grid-tile" data-testid="size-17" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 17</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$449</p></div></div></div><div data-component="grid-tile" data-testid="size-18" variantcount="25" class="css-aw1zls"><div data-component="tile-inner" class="css-pmdaq1"><p class="chakra-text css-hoqc8t" data-component="tile-value"> 18</p><div data-component="tile-subvalue" class="css-0"><p class="chakra-text css-h7cvs">$400</p></div></div></div></div>
L0rdLi4m
  • 1
  • 1

2 Answers2

0

Here's an easy solution: just point your browser to the buy URL with ?size=11 appended: https://stockx.com/buy/air-jordan-1-retro-high-og-chicago-reimagined-lost-and-found?size=11. That's what clicking the button seems to do.


If you want to do it the hard way, loop over the elements and pick the one with textContent.trim() === "11".

Selecting the elements is the missing piece. I see no such '[data-testid="size-11"]' selector. It's possible that you're being served a different site.

Here's what works for me based on the document I'm being served:

const puppeteer = require("puppeteer"); // ^19.7.2

const url =
  "https://stockx.com/buy/air-jordan-1-retro-high-og-chicago-reimagined-lost-and-found";

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  const ua =
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36";
  await page.setUserAgent(ua);
  await page.goto(url, {waitUntil: "domcontentloaded"});
  const sel = '[data-component="tile-value"]';
  await page.waitForSelector(sel);
  const navP = page.waitForNavigation({waitUntil: "networkidle2"});
  await page.$$eval(
    sel,
    els => els.find(e => e.textContent.trim() === "11").click()
  );
  await navP;
  console.log(page.url());
  await page.screenshot({path: "shoe.png", fullpage: true});
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

Note that I'm using finally to close the browser. initBrowser as you have it is flawed--the browser object is lost and you can never close it, hanging the process until it's killed by hand.

I suggest not writing functions until the code is working. Premature abstractions get in the way and add complexity. Once the code is functionally correct, then you can factor it out into a neat function or three.


Another approach that I didn't bother trying is something like:

const size = await page.waitForSelector("text/11");
await size.click();

The problem is that this can inadvertently target the wrong element. XPath is also possible. See this post for a general guide to selecting elements by text in Puppeteer.


Final note: they're using some bot detection, so if you get blocked then there's probably more work to be done, but that seems out of scope for this question.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
0

There a couple problems I can see:

  • the selector "div[data-testid='size-11'" should be "div[data-testid=size-11]",
  • make sure things load before clicking them : await page.waitForSelector("div[data-testid=size-11]");
  • await checkout() like in the code below.
  • your const page = await initBrowser(); should be outside of the function otherwise you'll get ReferenceError: page is not defined
const pt = require("puppeteer");

let browser;
(async () => {

    let url = 'https://stockx.com/buy/air-jordan-1-retro-high-og-chicago-reimagined-lost-and-found';
    const page = await initBrowser();

    async function initBrowser() {
        const browser = await pt.launch({headless: false, defaultViewport: null, slowMo: 10});
        const page = await browser.newPage();
        await page.goto(url, {waitUntil: 'networkidle0'});
        return page;
    }

    async function selectSize(size = 11) {        
        let select = await page.waitForSelector(`div[data-testid=size-${size}]`);
        await select.click();
    }


    async function checkout() {
        await selectSize();
        await page.setViewport({width: 1920, height: 1080})
        await page.screenshot({path: 'test.png'})
    }
    await checkout();

})().catch(err => console.error(err)). finally(() => browser ?. close());

idchi
  • 761
  • 1
  • 5
  • 15