Based on this response, is there a way (like with casperjs/phantomjs) to add our custom functions in page.evaluate() context ?
By example, include a file with a help
Another solution based on casperjs getElementByXPath()
and getElementsByXPath()
. The advantage is that we can use an xpath expression against a particular node (second argument).
window.$x = xPath => document
.evaluate(
xPath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
)
.singleNodeValue;
window.getElementByXPath = function getElementByXPath(expression, scope) {
scope = scope || document;
var a = document.evaluate(expression, scope, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (a.snapshotLength > 0) {
return a.snapshotItem(0);
}
};
window.getElementsByXPath = function getElementsByXPath(expression, scope) {
scope = scope || document;
var nodes = [];
var a = document.evaluate(expression, scope, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < a.snapshotLength; i++) {
nodes.push(a.snapshotItem(i));
}
return nodes;
};
Real life code sample :
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://99bitcoins.com/bitcoin-rich-list-top100/#addresses', { waitUntil: 'networkidle2' });
await page.addScriptTag({ path: './helperFunctions.js' });
const result = await page.evaluate(() => {
var obj = {};
var data = getElementsByXPath('//table[@class="t99btc-rich-list"]//tr');
for (var i = 1; i<=100; i++) {
obj[i] = {
"hash": getElementByXPath('./td/a', data[i]).innerText,
"balance": getElementByXPath('./td[3]', data[i]).innerText
}
}
return obj;
});
console.log(JSON.stringify(result, null, 4));
await browser.close();
})();