Sayalic
Sayalic

Reputation: 7650

Puppeteer: How to evaluate xpath with document.evaluate?

Given a hard Puppeteer task, I have to evaluate XPath in Puppeteer with context node. So I can't use page.$x.

I know it can be achieved by Javascript function document.evaluate(xpathExpression, contextNode, namespaceResolver, resultType, result), so I tried this code:

const puppeteer = require('puppeteer');

async function f(page, xpath) {
    try {
        return page.evaluate((xpath) => {
            return document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null)
        }, xpath)
    } catch (e) {
        console.log(e)
    }
}

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('http://personalitycore.com/a.html');
    let p = await f(page, '//p')
    console.log(p)
    await browser.close();
})();

And http://personalitycore.com/a.html:

<head>
</head>
<body>
<p>
text_node1
<span>span_node1</span>
text_node2
<span>span_node2</span>
</p>
</body>

And run my code:

/usr/local/bin/node /Users/xxxx/example.js
{}

It just returns an empty object.

But that script did well in Chrome:

enter image description here

Could anyone please give me some hints about evaluating XPath in Puppeteer with document.evaluate?

Upvotes: 1

Views: 1275

Answers (1)

vsemozhebuty
vsemozhebuty

Reputation: 13782

Unfortunately, page.evaluate() can only transfer serializable values (roughly, the values JSON can handle). As document.evaluate() returns a DOM element that is not serializable (it contains methods and circular references), it is replaced with an empty object. You need to return either serializable value (for example, an attribute or text content) or use something like page.evaluateHandle() and ElementHandle API.

Upvotes: 1

Related Questions