Passando para os dados do vídeo, também destaquei as secções relevantes do documento HTML. Aqui, devemos extrair uma lista de elementos, por isso analisamos primeiro os contentores pai e, em seguida, percorremos cada um deles.
Seguimos a mesma abordagem da secção anterior: escolher alguns seletores CSS únicos para localizar os dados de que precisamos, com foco nos seus ids. O código deve ficar mais ou menos assim:
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)
Quando executar o código, o resultado deverá ser uma lista de objetos JavaScript. Cada um deles deverá conter o título, o número de visualizações, a miniatura e a localização de cada elemento de vídeo na página.
No entanto, irá notar que, a partir de um certo ponto, a sua lista começa a ficar assim:
{
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'
},
Embora os elementos de vídeo ainda tenham uma miniatura e o seletor CSS não tenha mudado, o valor extraído é nulo. Isto acontece normalmente quando um site implementa o carregamento diferido, o que significa que o resto da lista é carregado à medida que se percorre a página até ao fundo.
Para resolver este problema, basta instruirmos o nosso script para percorrer a página do canal para baixo.
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 função recebe como parâmetros a nossa página aberta e um número de movimentos de rolagem. Em seguida, tenta percorrer a distância igual à altura da janela tantas vezes quantas o parâmetro scroll_number indicar. Estes movimentos são realizados a cada 1 segundo.
Agora basta chamar a função antes do trecho de código que extrai a lista de vídeos.
await autoScroll(page, 10)
await page.waitForTimeout(2 * 1000)
Adicionei um tempo de espera adicional de 2 segundos para que o site tenha tempo de carregar totalmente os elementos finais da lista. Ao executar o script novamente, poderá primeiro ver como os movimentos de rolagem ocorrem e, em seguida, que todos os elementos da lista têm um valor de miniatura.