20

How to get all images on the page with playwright? I'm able to get only one (ElementHandle) with following code, but not a collection.

const { chromium } = require("playwright");

class Parser {
  async parse(url) {
    const browser = await chromium.launch();
    const page = await browser.newPage();
    await page.goto(url);
    await page.waitFor("img");
    // TODO: get somehow collection of elements
    return await page.$("img");
  }
}

module.exports = Parser;

Somewhere in another module far far away:

const Parser = require("./path/to/dir/Parser.js");
const parser = new Parser();

parser
    .parse(body.url)
    .then(elemHandle => {
      // here I get only one ElementHandle object, but suppose to get an array or collection
    })
    .catch(err => {
      throw new Error(err);
    });

Node v.12.16.1

CoderDesu
  • 697
  • 1
  • 5
  • 14

7 Answers7

32

I have already found the answer. Need to use page.$$(selector) instead of page.$(selector) to grab like document.querySelectorAll(selector).

CoderDesu
  • 697
  • 1
  • 5
  • 14
7

As mentioned in the accepted answer, you can use await page.$$(selector). Here is a link to the page.$$ official documentation

You can also use the following code.

const result = await page.evaluate(selector => document.querySelectorAll(selector) , selector);

Here is a link to the page.evaluate official documentation

Charley Rathkopf
  • 4,720
  • 7
  • 38
  • 57
Shubham Sharma
  • 325
  • 5
  • 9
5
  • for playwright use: await page.$$(selector);
5

For counting, when trying to avoid the use of await page.$$(selector);, another alternative is to directly use LocatorAssertion:

await expect(locator).toHaveCount(n);

Link to official documentation

3

There is another way to work with a list of elements you can read from the documentation. And I like it much more https://playwright.dev/docs/locators#lists

So you just select using the page.locator and after that, you can interact with each element using for loop or selected the needed element using .nth()

2

You want to use the new method locator.all(), added in v1.29, to iterate over all matching elements:

// returns all images on the page & stores them in an array
const images = await page.getByRole('img').all();

The usage of await page.$$(selector); is discouraged. Use locator-based page.locator() instead. You can read about the method here.

Manuel Abascal
  • 5,616
  • 5
  • 35
  • 68
-1

Locator seems to be the current way forward. page.$$(img) is discouraged.

Instead use:

const imageList = await page.locator('img);

For count:

const imageList = await page.locator('img');
console.log('images: ', await imageList.count());

More information on https://playwright.dev/docs/locators

However, to answer the question of getting all images depending on how you to store them but Ill use an array.

const tmpArray = [];
const imageList = await page.locator('img');
for (let i = 0; i < await imageList.count(); i++) {
    const element = await imageList.nth(i).getAttribute('src');
    tmpArray.push(element)
}

You can also store imageList.count() in a variable and use that instead in your for loop

akwasiijunior
  • 105
  • 2
  • 7
  • This is so ugly, just to iterate over a list of elements you cant use the list directly but instead have to get the count and call the nth child by the index... – Benny Alex Jun 13 '23 at 20:13
  • @BennyAlex not sure what you're trying to get at but the OP wants to get all the images on a page. How OP intends to use the collection isnt specified but my answer provides the OP with a solution to store the source of all images in an array. If he or she wants to pop, at or find for later use then this is a viable solution – akwasiijunior Jul 04 '23 at 08:24