'Puppeteer; Get Values within an element

I'm stuck here.

I got multiple rows with class rowcontent.

I get them like that:

const rows = await page.$$('.row-content');

Almost every row in rows got many spans with the class named cashspan.

I would like to get those values in an array called 'values'.

I've tried much to many things with no success

for (let m = 0; m < rows.length; m++) {
        const row = await rows[m];
const values = await row.evaluate(() => Array.from(row.getElementsByClassName('cashspan'), element => element.textContent));
 console.log(values)
}

this was the latest thing I've tried.

With

const spancashs = await page.evaluate(() => Array.from(document.querySelectorAll('[class="cashspan"]'), element => element.textContent));

I get all the elements on the page. But i need them for every row. Hope that makes sense.

Update1

Example:

<div class="container">
        <div class="row-content">
            <div class="someclass1">
                <div class="someclass2">
                    <span class="cashspan">1</span>
                </div>
            </div>
            <div class="someclass3">
                <div class="someclass4">
                    <span class="cashspan">2</span>
                </div>
            </div>
            <div class="someclass5">
                <div class="someclass6">
                    <span class="cashspan">3</span>
                </div>
            </div>
        </div>
        <div class="row-content">
            <div class="someclass7">
                <div class="someclass8">
                    <span class="cashspan">4</span>
                </div>
            </div>
            <div class="someclass9">
                <div class="someclass10">
                    <span class="cashspan">5</span>
                </div>
            </div>
            <div class="someclass11">
                <div class="someclass12">
                    <span class="cashspan">6</span>
                </div>
            </div>
        </div>
        <div class="row-content">
            <div class="someclass13">
                <div class="someclass14">
                    <span class="cashspan">7</span>
                </div>
            </div>
            <div class="someclass15">
                <div class="someclass16">
                    <span class="cashspan">8</span>
                </div>
            </div>
            <div class="someclass17">
                <div class="someclass18">
                    <span class="cashspan">9</span>
                </div>
            </div>
        </div> 
     </div>

Code:

 const rows = await page.$$('.row-content');
    
 for (let i = 0; i < rows.length; i++) {
        const row = await rows[i];
        const values = await row.evaluate(() => 
        Array.from(row.getElementsByClassName('cashspan'), element => 
        element.textContent));
   console.log(values)
 }

I'm trying to get all cashspan values in every row-content container. The output for this example should be:

[ 1, 2, 3 ]
[ 4, 5, 6 ]
[ 7, 8 ,9 ]


Solution 1:[1]

Following up on the comments, the row variable inside of evaluate()'s callback was never defined in browser context. Adding that variable to the evaluate() callback parameter list worked for me on the provided example. This is the only non-cosmetic change below:

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

const html = `
<body>
<div class="container">
  <div class="row-content">
    <div class="someclass1">
      <div class="someclass2">
        <span class="cashspan">1</span>
      </div>
    </div>
    <div class="someclass3">
      <div class="someclass4">
        <span class="cashspan">2</span>
      </div>
    </div>
    <div class="someclass5">
      <div class="someclass6">
        <span class="cashspan">3</span>
      </div>
    </div>
  </div>
  <div class="row-content">
    <div class="someclass7">
      <div class="someclass8">
        <span class="cashspan">4</span>
      </div>
    </div>
    <div class="someclass9">
      <div class="someclass10">
        <span class="cashspan">5</span>
      </div>
    </div>
    <div class="someclass11">
      <div class="someclass12">
        <span class="cashspan">6</span>
      </div>
    </div>
  </div>
  <div class="row-content">
    <div class="someclass13">
      <div class="someclass14">
        <span class="cashspan">7</span>
      </div>
    </div>
    <div class="someclass15">
      <div class="someclass16">
        <span class="cashspan">8</span>
      </div>
    </div>
    <div class="someclass17">
      <div class="someclass18">
        <span class="cashspan">9</span>
      </div>
    </div>
  </div>
</div>
</body>
`;

let browser;
(async () => {
  browser = await puppeteer.launch({headless: true});
  const [page] = await browser.pages();
  await page.setContent(html);
  const rows = await page.$$('.row-content');

  for (let i = 0; i < rows.length; i++) {
    const row = await rows[i];
    const values = await row.evaluate(row => Array.from(
      row.getElementsByClassName('cashspan'),
      element => element.textContent
    ));
    console.log(values);
  }
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

If this isn't working on the live site, the problem could be due to any number of JS behaviors, visibility or timing issues, so more detail would be necessary to accurately reproduce the problem.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ggorlen