Je connais les méthodes courantes telles que evaluate
pour capturer les éléments dans puppeteer
, mais je suis curieux de savoir pourquoi je ne peux pas obtenir l'attribut href
dans une approche de type JavaScript comme
const page = await browser.newPage();
await page.goto('https://www.example.com');
let links = await page.$$('a');
for (let i = 0; i < links.length; i++) {
console.log(links[i].getAttribute('href'));
console.log(links[i].href);
}
await page.$$('a')
renvoie un tableau avec ElementHandles - ce sont des objets avec leur propre API spécifique à l'élève, ils n'ont pas d'API DOM habituelle pour les éléments HTML ou les nœuds DOM. Vous devez donc soit récupérer les attributs/propriétés dans le contexte du navigateur via page.evaluate()
, soit utiliser l'API ElementHandles plutôt compliquée. Voici un exemple dans les deux sens:
'use strict';
const puppeteer = require('puppeteer');
(async function main() {
try {
const browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.goto('https://example.org/');
// way 1
const hrefs1 = await page.evaluate(
() => Array.from(
document.querySelectorAll('a[href]'),
a => a.getAttribute('href')
)
);
// way 2
const elementHandles = await page.$$('a');
const propertyJsHandles = await Promise.all(
elementHandles.map(handle => handle.getProperty('href'))
);
const hrefs2 = await Promise.all(
propertyJsHandles.map(handle => handle.jsonValue())
);
console.log(hrefs1, hrefs2);
await browser.close();
} catch (err) {
console.error(err);
}
})();
Je ne sais pas pourquoi c'est une telle douleur, mais cela a été trouvé lorsque je l'ai rencontré il y a quelque temps.
async function getHrefs(page, selector) {
return await page.$$eval(selector, anchors => [].map.call(anchors, a => a.href));
}