How to use "p selector" to select multiple elements (inside shadow DOMs) in Puppeteer?

171 views Asked by At

I am aware of page.$$ but it uses document.querySelectorAll. I want to search inside shadow DOMs and for that I use Puppeteer's extended selector syntax (which they call "p selector") - >>>. It works great with page.waitForSelector but that api only returns the first match, not an array of ElementHandler. Using the extended syntax with page.$$ does not work. So what is the solution?

1

There are 1 answers

0
idchi On

You can use >>> with page.$$ and page.$$eval, its like using pierce/

Code (Example):

const puppeteer = require("puppeteer");

let browser;
(async () => {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();
    let url = "https://webforms.garantibbva.com.tr/currency-convertor/?lang=en";

    await page.goto(url, { waitUntil: "networkidle0", timeout: 15000 });
    await page.waitForSelector("body");
    
    // ex. for page.$$eval
    //let selector = 'pierce/div.currency-table > div.row';
    let selector = "div >>> div.currency-table > div.row";
    let dataArr = await page.$$eval(selector, el => el.map(x => x.textContent.trim()));

    // ex. for page.$$
    let selector2 = "* >>> div.cellCurrTextLeft";
    let rows = await page.$$(selector2);
    let list =[];
    for (let row of rows) {
        let curr = await row.$eval("span", el => el.textContent);
        list.push(curr);
    }

    //ignore start (just formats the data recieved)
    dataArr = dataArr.slice(1);
    let data = dataArr.map((x, i, d) => { return d[i].replace(/,/g, '.').replace(/ +?/g, '').replace(/[\n]{2,}/g, "\n").split('\n'); });
    data = data.map((x, i, d) => [d[i][0], d[i][2], d[i][3]]);
    //ignore end

    console.log(data);
    console.log(list);

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

If you still have a problem post your code.