J'essaie d'extraire le titre de cette page en utilisant Puppeteer : https://www.nordstrom.com/s/zella-high-waist-studio-pocket-7-8-leggings/5460106
J'ai le code suivant,
(async () => {
const browser = await puppet.launch({ headless: true });
const page = await browser.newPage();
await page.goto(req.params[0]); //this is the url
title = await page.evaluate(() => {
Array.from(document.querySelectorAll("meta")).filter(function (
el
) {
return (
(el.attributes.name !== null &&
el.attributes.name !== undefined &&
el.attributes.name.value.endsWith("title")) ||
(el.attributes.property !== null &&
el.attributes.property !== undefined &&
el.attributes.property.value.endsWith("title"))
);
})[0].attributes.content.value ||
document.querySelector("title").innerText;
});
que j'ai testé en utilisant la console du navigateur et même en utilisant l'option {headless : false } de Puppeteer. Il fonctionne comme prévu dans le navigateur, mais lorsque je l'exécute avec node, il me donne l'erreur suivante.
10:54:21 AM web.1 | (node:10288) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'attributes' of undefined
10:54:21 AM web.1 | at __puppeteer_evaluation_script__:14:20
Donc, quand je lance le même Array.from ...querySelectorAll("meta")...
dans le navigateur, j'obtiens la chaîne attendue :
"Zella High Waist Studio Pocket 7/8 Leggings | Nordstrom"
Je commence à penser que je fais quelque chose de mal avec les promesses asynchrones, car c'est la partie qui est différente. Quelqu'un peut-il m'indiquer la bonne direction ?
EDIT : Comme suggéré, j'ai testé en utilisant document.title, qui devrait être là, mais il a également retourné null. Voir le code et le journal ci-dessous :
console.log(
"testing the return",
(async () => {
const browser = await puppet.launch({ headless: true });
const page = await browser.newPage();
await page.goto(req.params[0]); //this is the url
try {
title = await page.evaluate(() => {
const title = document.title;
const isTitleThere = title == null ? false : true;
//recently read that this checks for undefined as well as null but not an
//undeclared var
return {
title: title,
titleTitle: title.title,
isTitleThere: isTitleThere,
};
});
} catch (error) {
console.log(error, "There was an error");
}
11:54:11 AM web.1 | testing the return Promise { <pending> }
11:54:13 AM web.1 | { title: '', isTitleThere: true }
Est-ce que ça a un rapport avec la page unique de l'application Bs ? Je pensais que Puppeteer gérait ça parce qu'il charge tout en premier.
EDIT : J'ai ajouté les lignes networkidle et j'attends 8000 millisecondes, comme suggéré. Le titre est toujours vide. Code ci-dessous et log :
await page.goto(req.params[0], { waitUntil: "networkidle2" });
await page.waitFor(8000);
console.log("done waiting");
title = await page.$eval("title", (el) => el.innerText);
console.log("title: ", title);
console.log("done retrieving");
12:36:39 PM web.1 | done waiting
12:36:39 PM web.1 | title:
12:36:39 PM web.1 | done retreiving
EDIT : PROGRÈS !! Merci à theDavidBarton. Il semble que headless doive être false pour que cela fonctionne ? Quelqu'un sait-il pourquoi ?