Pasando a los datos del vídeo, también he resaltado las secciones relevantes del documento HTML. Aquí, debemos extraer una lista de elementos, por lo que primero miramos los contenedores principales y luego iteramos a través de cada uno de ellos.
Seguimos el mismo enfoque de la sección anterior: elegimos algunos selectores CSS únicos para localizar los datos que necesitamos, centrándonos en sus ids. El código debería tener un aspecto similar a este:
const videos = await page.evaluate(() => {
const videosEls = Array.from(document.querySelectorAll('div#dismissible'))
return videosEls.map(video => {
const titleEl = video.querySelector('yt-formatted-string#video-title');
const viewsEl = video.querySelector('div#metadata-line > span');
const thumbnailEl = video.querySelector('yt-image.ytd-thumbnail > img');
const locationEl = video.querySelector('a#thumbnail');
return {
title: titleEl ? titleEl.textContent : null,
views: viewsEl ? viewsEl.textContent : null,
thumbnail: thumbnailEl ? thumbnailEl.getAttribute('src') : null,
location: locationEl ? locationEl.getAttribute('href') : null
}
})
})
console.log(videos)
Al ejecutar el código, el resultado debería ser una lista de objetos JavaScript. Cada uno de ellos debería contener el título, el número de visualizaciones, la miniatura y la ubicación de cada elemento de vídeo en la página.
Sin embargo, notarás que, a partir de cierto punto, tu lista empieza a tener este aspecto:
{
title: 'GitLab CI/CD Full Course released - CI/CD with Docker | K8s | Microservices!',
views: '114K views',
thumbnail: null,
location: '/watch?v=F7WMRXLUQRM'
},
{
title: 'Kubernetes Security Best Practices you need to know | THE Guide for securing your K8s cluster!',
views: '103K views',
thumbnail: null,
location: '/watch?v=oBf5lrmquYI'
},
{
title: 'How I learn new technologies as a DevOps Engineer (without being overwhelmed)',
views: '366K views',
thumbnail: null,
location: '/watch?v=Cthla7KqU04'
},
{
title: 'Automate your Multi-Stage Continuous Delivery and Operations | with Keptn',
views: '59K views',
thumbnail: null,
location: '/watch?v=3EEZmSwMXp8'
},
Aunque los elementos de vídeo siguen teniendo una miniatura y el selector CSS no ha cambiado, el valor extraído es nulo. Esto suele ocurrir cuando un sitio web implementa la carga diferida, lo que significa que el resto de la lista se carga a medida que te desplazas hacia la parte inferior de la página.
Para resolver este problema, solo tenemos que indicar a nuestro script que se desplace hacia abajo en la página del canal.
async function autoScroll(page: any, scroll_number: number): Promise<any> {
await page.evaluate(async (scroll_number: number) => {
await new Promise((resolve) => {
let totalHeight = 0;
const timer = setInterval(() => {
const scrollHeight = window.innerHeight * scroll_number;
window.scrollBy(0, window.innerHeight);
totalHeight += window.innerHeight;
if (totalHeight > scrollHeight) {
clearInterval(timer);
resolve(true);
}
}, 1000);
});
}, scroll_number);
}
Esta función toma como parámetros nuestra página abierta y un número de movimientos de desplazamiento. A continuación, intenta desplazarse una distancia igual a la altura de la ventana tantas veces como le indique el parámetro scroll_number. Estos movimientos se realizan cada 1 segundo.
Ahora solo tienes que llamar a la función antes del fragmento de código que extrae la lista de vídeos.
await autoScroll(page, 10)
await page.waitForTimeout(2 * 1000)
He añadido un tiempo de espera adicional de 2 segundos para que el sitio web tenga tiempo de cargar completamente los elementos finales de la lista. Al ejecutar el script de nuevo, primero podrás ver cómo se producen los movimientos de desplazamiento y, a continuación, que todos los elementos de la lista tienen un valor de miniatura.