Estoy intentando iterar a través de una lista de URL y, en lugar de que el titiritero cargue cada página, solo carga una. ¿Qué puedo hacer para que esto funcione?
async function main() { const browser = await puppeteer.launch({headless: false}); const page = await browser.newPage(); await page.setViewport({width: 1200, height: 720}); await page.goto('https://s23.a2zinc.net/clients/acmedia/americancoatingsshow2022/Public/Exhibitors.aspx?Index=All#', { waitUntil: 'networkidle0' }); // wait until page load const hrefs = await page.$$eval('a', as => as.map(a => a.href)); for (let i = 0; i < hrefs.length; i++) { const url = hrefs[i]; if (url.includes('eBooth.aspx')) { console.log(url) const page = await browser.newPage() await page.goto(`${url}`); await page.waitForNavigation({ waitUntil: 'networkidle0' }); } } main();El principal problema es una página de await page.waitForNavigation({ waitUntil: 'networkidle0' }); que no se resolverá. page.goto ya espera la navegación, por lo que le está pidiendo a Titiritero que espere una navegación que nunca sucederá.
Solo use page.waitForNavigation si está haciendo algo para activar una navegación, no como parte de una llamada típica de page.goto . Elimine esta línea y su código debería funcionar (más o menos) como se esperaba.
Además, está abriendo una página completamente nueva (pestaña del navegador) por enlace. Según mi cuenta, son 360 pestañas, que pueden hacer que la mayoría de las computadoras se queden sin memoria. Es mejor navegar una sola página repetidamente o cerrar páginas después de que haya terminado de hacer lo que planea hacer en estas páginas. Si eso es demasiado lento, intente ejecutar fragmentos en paralelo o usar una cola de tareas.
Además, los enlaces están disponibles en HTML estático, por lo que es posible que no necesite Titiritero aquí , nuevamente, dependiendo de lo que planee hacer en cada página. Si puede obtener todos los datos de cada página de forma estática, podría tener una aceleración masiva, completando raspaduras de 360 con fetch / cheerio en una fracción del tiempo que le tomaría a Puppeteer.
Si se queda con Puppeteer para eludir la detección o lidiar con JS/interactividad, considere usar domcontentloaded en lugar de networkidle0 , que suele ser innecesariamente estricto y lento. La publicación del blog vinculada explica la diferencia entre las diversas condiciones de carga. Vea también mi respuesta en el hilo canónico Puppeteer, espere hasta que la página esté completamente cargada para una inmersión más profunda en la carga de la página en Puppeteer.
a[href] es un selector más preciso que a , porque es posible que algunos anclajes a no tengan href y deban descartarse para evitar que aparezcan indefinidos.
Así es como escribiría esto (con la advertencia antes mencionada de que Puppeteer podría no ser necesario en absoluto):
const puppeteer = require("puppeteer"); // ^14.3.0 let browser; (async () => { browser = await puppeteer.launch({headless: false}); const [page] = await browser.pages(); await page.setViewport({width: 1200, height: 720}); const url = "https://s23.a2zinc.net/clients/acmedia/americancoatingsshow2022/Public/Exhibitors.aspx?Index=All#"; await page.goto(url, {waitUntil: "domcontentloaded"}); const hrefs = await page.$$eval("a[href]", els => els.map(a => a.href).filter(e => e.includes("eBooth.aspx")) ); console.log(hrefs.length); // => 360 for (const url of hrefs) { await page.goto(url); // page is loaded; do your thing on this page } })() .catch(err => console.error(err)) .finally(() => browser.close()) ;