The documentation on page.$(selector) says it returns a promise containing an ElementHandle.
But the documentation on ElementHandle is a bit lacking.
It says it "represents a DOM element", but what does that really mean? And if does represent the DOM, why can't the contents of the ElementHandle be inspected?
It also says, "prevents DOM element from garbage collection unless the handle is disposed." Why would a DOM element get garbage collected if the browser is still on the page?
This came up because I thought it'd be simple to grab the text from an element on the page, so I tried,
const text = await page.$('#text').textContent;
which returned undefined
. So I tried,
const text = await page.$('#text').textContent();
which threw an error.
Turns out the correct way is
const text = await page.evaluate(() => document.querySelector('#text').textContent);
ElementHandle prevents the DOM element from being garbage-collected unless the handle is disposed. ElementHandles are auto-disposed when their origin frame gets navigated. ElementHandle instances can be used as arguments in Page.
JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is disposed . JSHandles are auto-disposed when their origin frame gets navigated or the parent context gets destroyed. JSHandle instances can be used as arguments in page.
With ElementHandle can you still access to properties like textContent
but in "Puppeteer way".
Firstly you must .getProperty()
on ElementHandle
, and after that convert it to .jsonValue()
. Remember that all this operations returns poromises so you should await
on all of them like this:
await (await (await page.$('#text')).getProperty('textContent')).jsonValue();
Here is full working example:
const puppeteer = require('puppeteer');
const html = `
<html>
<body>
<div id="text">Sample content</div>
</body>
</html>`;
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(`data:text/html,${html}`);
const text = await page.evaluate(() => document.querySelector('#text').textContent);
const text2 = await (await (await page.$('#text')).getProperty('textContent')).jsonValue();
console.log(text);
console.log(text2);
await browser.close();
})();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With