Screenshot for each DOM node

Viewed 7892

How can I create screenshots for every DOM node in any site?

I tried to use headless browser (puppeteer) and it's working only when I know XPath or Selector of some element. But how to I can receive XPath or Selector for all elements?

async function screenshotDOMElement(opts = {}) {
const padding = 'padding' in opts ? opts.padding : 0;
const path = 'path' in opts ? opts.path : null;
const selector = opts.selector;

if (!selector)
    throw Error('Please provide a selector.');

const rect = await page.evaluate(selector => {
    const element =
     document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    if (!element)
        return null;
    const {x, y, width, height} = element.getBoundingClientRect();
    console.log (x,y,width,height)
    return {left: x, top: y, width, height, id: element.id};
}, selector);

if (!rect)
    throw Error(`Could not find element that matches selector: ${selector}.`);

return await page.screenshot({
    path,
    clip: {
        x: rect.left - padding,
        y: rect.top - padding,
        width: rect.width + padding * 2,
        height: rect.height + padding * 2
    }
});
}

Also I tried to use HtmlAgilityPack (C#) and enumerate each node in HtmlDocument by XPath, but this XPath can't work with puppeteer

I need to use puppeteer 'cos it's the best instrument for screenshot-task by XPath or Selector

Who can help me?

1 Answers

With puppeteer, you don't need to use the whole page screenshot anymore, since it has elementHandle.screenshot([options]). Here's what you can do:

const browser = await puppeteer.launch();

const page = await browser.newPage();
await page.goto('https://example.com');

// get a list of all elements - same as document.querySelectorAll('*')
const elements = await page.$$('*')

for (let i = 0; i < elements.length; i++) {
  try {
    // get screenshot of a particular element
    await elements[i].screenshot({path: `${i}.png`})
  } catch(e) {
    // if element is 'not visible', spit out error and continue
    console.log(`couldnt take screenshot of element with index: ${i}. cause: `,  e)
  }
}
await browser.close();

Notice than puppeteer fails to get screenshots for some elements that are invisible or covered by other elements, etc. In such a case, you need to catch an error and move on.

Related