Voltar ao blogue
Guias
Raluca PenciucLast updated on Mar 31, 20269 min read

Como extrair dados do YouTube como um profissional: um guia completo

Como extrair dados do YouTube como um profissional: um guia completo

Precisa de dados de um site, mas as APIs disponíveis não são suficientes? O web scraping é a resposta que procurava. Com o web scraping, pode extrair dados de um site de forma mais abrangente e flexível.

Neste artigo, vamos mergulhar no mundo do web scraping, analisando mais de perto como fazer scraping no YouTube, uma das plataformas de partilha de vídeos mais populares. Embora o YouTube forneça uma API para aceder aos dados, o web scraping pode oferecer uma gama mais ampla de opções para extrair dados dos canais do YouTube.

Começaremos por configurar um ambiente de desenvolvimento e abordar os pré-requisitos para o web scraping, passando depois ao processo propriamente dito de como fazer web scraping no YouTube. Ao longo do caminho, daremos dicas para melhorar as suas competências de web scraping e discutiremos por que razão utilizar um scraper profissional pode ser uma escolha melhor do que criar o seu próprio.

No final deste artigo, estará equipado com o conhecimento e as competências necessárias para extrair dados do YouTube de forma eficaz, como um profissional!

Pré-requisitos

Primeiro, terá de se certificar de que tem o Node.js instalado no seu computador. Se ainda não o tiver, aceda ao site oficial do Node.js e siga as instruções para o seu sistema operativo específico. É importante notar que deve descarregar a versão de Suporte a Longo Prazo (LTS) para garantir que tem uma versão estável e suportada.

Em seguida, terá de instalar o Node.js Package Manager (NPM). Este deverá vir automaticamente com a instalação do Node.js, mas é sempre bom verificar novamente.

No que diz respeito ao seu ambiente de programação, sinta-se à vontade para usar qualquer IDE que preferir. Vou usar o Visual Studio Code neste tutorial porque é flexível e fácil de usar, mas qualquer IDE serve. Basta criar uma nova pasta para o seu projeto e abrir um terminal. Execute o seguinte comando para configurar um novo projeto Node.js:

npm init -y

Isto irá criar um ficheiro package.json predefinido para o seu projeto. Pode modificar este ficheiro a qualquer momento para se adequar às suas necessidades.

Agora é hora de instalar o TypeScript e as definições de tipos para o Node.js. O TypeScript é uma escolha popular entre a comunidade JavaScript devido à sua tipagem estática opcional, que ajuda a evitar erros de tipo no seu código. Para instalá-lo, execute o seguinte comando:

npm install typescript @types/node --save-dev

Para verificar se a instalação foi bem-sucedida, pode executar o seguinte comando:

npx tsc --version

Por fim, terá de criar um ficheiro de configuração tsconfig.json na raiz do diretório do seu projeto. Este ficheiro define as opções do compilador para o seu projeto. Se quiser saber mais sobre este ficheiro e as suas propriedades, consulte a documentação oficial do TypeScript.

Em alternativa, pode copiar e colar o código seguinte no seu ficheiro tsconfig.json:

{

   "compilerOptions": {

       "module": "commonjs",

       "esModuleInterop": true,

       "target": "es2017",

       "moduleResolution": "node",

       "sourceMap": true,

       "outDir": "dist"

   },

   "lib": ["es2015"]

}

Para o processo de scraping, vou utilizar o Puppeteer, uma biblioteca de navegador headless para Node.js que permite controlar um navegador web e interagir com sites de forma programática. Para instalar o Puppeteer, execute o seguinte comando:

npm install puppeteer

Extração dos dados

Para este guia, vou fazer o scraping de um canal do YouTube com tutoriais relacionados com DevOps: https://www.youtube.com/@TechWorldwithNana/videos. Os dados que estou a analisar em particular são:

  • o avatar do canal
  • o nome do canal
  • o nome de utilizador do canal
  • o número de subscritores do canal
  • os títulos de todos os vídeos
  • o número de visualizações de todos os vídeos
  • a miniatura de todos os vídeos
  • o URL de todos os vídeos

Vou incluir capturas de ecrã para cada secção e vou recorrer a seletores CSS para localizar os dados no DOM. Este é o método mais simples e direto, a menos que o site em questão seja conhecido por ter uma estrutura DOM instável.

Se ainda não conheces os seletores CSS, consulta esta ficha de referência abrangente que te ajudará a começar num instante.

Vamos começar por criar uma pasta src e o ficheiro index.ts, onde escreveremos o código. Agora, basta abrir um navegador e aceder ao URL de destino:

import puppeteer from 'puppeteer';

async function scrapeChannelData(channelUrl: string): Promise<any> {

    // Launch Puppeteer

    const browser = await puppeteer.launch({

        headless: false,

    	  args: ['--start-maximized'],

    	  defaultViewport: null

    });

    // Create a new page and navigate to the channel URL

    const page = await browser.newPage();

    await page.goto(channelUrl);

    // Close the browser

    await browser.close();

}

scrapeChannelData("https://www.youtube.com/@TechWorldwithNana/videos");

Para fins de depuração visual, vou abrir o navegador no modo não headless. Se pretendes alargar o teu caso de uso em grande escala, recomendo que experimentes o modo headless.

Para executar o script, tem de o compilar primeiro e, em seguida, executar o ficheiro JavaScript gerado. Para facilitar as coisas, podemos definir um script no ficheiro package.json que trate destas duas etapas por nós. Basta editar a secção scripts do seu ficheiro package.json da seguinte forma:

"scripts": {

    "test": "npx tsc && node dist/index.js"

},

Agora, tudo o que tem de fazer para executar o seu código é executar o seguinte comando:

npm run test

Desde a primeira execução, notamos um primeiro problema: a caixa de diálogo de consentimento de cookies em ecrã inteiro que nos impede de aceder aos dados.

Felizmente, está visível na janela de visualização, pelo que podemos usar as Ferramentas de Programador para encontrar o seu identificador e clicar nele.

Também adicionamos um tempo de espera extra para permitir que a navegação seja concluída. O código ficará assim:

await page.waitForSelector('button[aria-label="Accept all"]')

await page.click('button[aria-label="Accept all"]')

await page.waitForTimeout(10 * 1000)

Informações do canal

Na captura de ecrã abaixo, podemos ver destacadas as secções que contêm os dados do canal que queremos extrair.

Uma boa regra prática para localizar facilmente os elementos HTML é escolher seletores CSS únicos. Por exemplo, para extrair o avatar do canal, vou escolher o elemento HTML personalizado yt-img-shadow com o id avatar. Em seguida, extraio o atributo src do seu elemento filho img.

const channelAvatar = await page.evaluate(() => {

    const el = document.querySelector('yt-img-shadow#avatar > img');

    return el ? el.getAttribute('src') : null;

});

console.log(channelAvatar)

Para o nome do canal, temos o conteúdo de texto do elemento yt-formatted-string com o id text.

const channelName = await page.evaluate(() => {

    const el = document.querySelector('yt-formatted-string#text');

    return el ? el.textContent : null;

});

console.log(channelName)

Para obter o identificador do canal, localizaremos o elemento yt-formatted-string com o id channel-handle e extrairemos o seu conteúdo de texto.

const channelHandle = await page.evaluate(() => {

    const el = document.querySelector('yt-formatted-string#channel-handle');

    return el ? el.textContent : null;

});

console.log(channelHandle)

E, finalmente, para o número de subscritores do canal, basta aceder ao elemento yt-formatted-string com o id subscriber-count e obter o seu conteúdo de texto.

const subscriberCount = await page.evaluate(() => {

    const el = document.querySelector('yt-formatted-string#subscriber-count');

    return el ? el.textContent : null;

});

console.log(subscriberCount)

Ao executar o script novamente, deverá ver o seguinte resultado:

https://yt3.googleusercontent.com/kXyR8Aa32KXnZWVdkAFUYK5utM752kSJPHGtYiJ4ev6BmdFHi-dl1EFbI3TogmHBjszwc7m2=s176-c-k-c0x00ffffff-no-rj

TechWorld with Nana

@TechWorldwithNana

709K subscribers

Dados do vídeo

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.

Evite ser bloqueado

Embora o guia até este ponto tenha parecido fácil, existem vários desafios que os web scrapers costumam enfrentar. O YouTube, em particular, implementa muitas técnicas antibot para impedir que scripts automatizados extraiam os seus dados.

Algumas dessas técnicas são:

  • CAPTCHAs: resolver CAPTCHAs pode ser demorado e difícil para um scraper, o que pode servir como um impedimento para os bots.
  • Desafios de JavaScript: podem incluir tarefas como resolver problemas matemáticos, completar um CAPTCHA ou encontrar um elemento específico na página. Um bot que não consiga completar o desafio será detetado e potencialmente bloqueado.
  • Verificações do User-Agent: o YouTube pode verificar a string do user-agent das solicitações recebidas para verificar se elas provêm de um navegador ou de um scraper. Se a string do user-agent não for reconhecida como um navegador válido, a solicitação poderá ser bloqueada.
  • Bloqueio de IP: o YouTube pode bloquear pedidos provenientes de determinados endereços IP que sejam conhecidos por estarem associados a bots ou a atividades de scraping.
  • Honeypots: O YouTube pode utilizar honeypots, que são elementos ocultos na página visíveis apenas para bots. Se for detetado um bot a interagir com um honeypot, este pode ser identificado e bloqueado.

Lidar com cada uma destas questões pode aumentar significativamente a complexidade e o custo do seu código de scraper. É aqui que as APIs de scraping desempenham um papel importante, uma vez que tratam destes problemas por predefinição e estão disponíveis a um preço mais baixo.

A WebScrapingAPI é um exemplo desse tipo de serviço. Oferece funcionalidades poderosas para evitar técnicas de deteção de bots e extrair com precisão os dados de que necessita.

Podemos experimentar rapidamente a WebScrapingAPI instalando o SDK do Node.js no nosso pequeno projeto:

npm i webscrapingapi

Agora, aceda à página inicial para criar uma conta, o que lhe dará automaticamente a sua chave de API e um período de teste gratuito. A chave de API pode ser encontrada no painel de controlo e irá utilizá-la para autenticar os seus pedidos à API:

E é tudo, já pode começar a programar!

import webScrapingApiClient from 'webscrapingapi';

const client = new webScrapingApiClient("YOUR_API_KEY");

async function exampleUsage(target_url: string) {

    const api_params = {

        'render_js': 1,

    	  'proxy_type': 'datacenter',

    	  'country': 'us',

    	  'timeout': 60000,

    	  'js_instructions': JSON.stringify([

            {

                action: "click",

                selector: 'button[aria-label="Accept all"]',

                timeout: 10000

         	}

    	  ]),

    	  'extract_rules': JSON.stringify({

        	avatar: {

                selector: "yt-img-shadow#avatar > img",

                output: "@src",

        	},

        	name: {

                selector: "yt-formatted-string#text",

                output: "text",

        	},

        	handle: {

                selector: "yt-formatted-string#channel-handle",

                output: "text",

        	},

        	subscribers: {

                selector: "yt-formatted-string#subscriber-count",

                output: "text",

        	},

        	videoTitles: {

                selector: "yt-formatted-string#video-title",

                output: "text",

                all: "1"

        	},

        	videoViews: {

                selector: "div#metadata-line > span",

                output: "text",

                all: "1"

        	},

        	videoThumbnails: {

                selector: "yt-image.ytd-thumbnail > img",

                output: "@src",

                all: "1"

        	},

        	videoLocations: {

                selector: "a#thumbnail",

                output: "@href",

                all: "1"

        	},

        })

    }

    const response = await client.get(target_url, api_params);

    if (response.success) {

        console.log(response.response.data);

    } else {

        console.log(response.error.response.data);

    }

}

exampleUsage("https://www.youtube.com/@TechWorldwithNana/videos");

Traduzimos o algoritmo e os seletores CSS descritos anteriormente para a API. O parâmetro “js_instructions” irá lidar com a janela de cookies, clicando no botão “Aceitar tudo”. Por fim, o parâmetro “extract_rules” irá lidar com a extração de dados.

const scroll_number = 10

let scroll_index = 0

for (let i = 0; i < scroll_number; i++) {

    const js_instructions_obj = JSON.parse(api_params.js_instructions)

    js_instructions_obj.push({

        action: "scrollTo",

        selector: `ytd-rich-grid-row.ytd-rich-grid-renderer:nth-child(${scroll_index + 3})`,

        block: "end",

     	  timeout: 1000

    })

    api_params.js_instructions = JSON.stringify(js_instructions_obj)

    scroll_index += 3

}

Depois, mesmo antes de enviar a solicitação, lembre-se de ajustar também a lógica de rolagem. Isso será um pouco diferente, pois instruímos a API a rolar até a terceira linha de vídeos 10 vezes.

Conclusão

Neste artigo, explorámos o fascinante campo do web scraping e aprendemos a extrair dados do YouTube utilizando o Node.js e o Puppeteer. Abordámos a configuração necessária para o web scraping, bem como o processo de extração de dados de canais do YouTube.

O web scraping pode ser uma ferramenta incrivelmente útil para aceder a dados de sites. No entanto, é importante ter em mente os vários desafios e considerações que o acompanham. Estes podem incluir CAPTCHAs, conteúdo dinâmico, limitação de taxa ou alterações no site.

Se está a pensar em extrair dados do YouTube ou de qualquer outro site, é essencial ponderar os prós e os contras e determinar se o web scraping é a melhor solução para as suas necessidades. Em alguns casos, utilizar uma API ou adquirir dados de uma fonte fiável pode ser uma opção mais adequada do que o scraping.

Independentemente da abordagem que escolher, é crucial respeitar os termos de serviço e as leis de direitos de autor que se aplicam aos dados a que está a aceder. E se decidir extrair dados do YouTube, lembre-se de utilizar um scraper profissional para garantir que obtém dados precisos e atualizados de forma segura e eficiente.

Espero que este artigo tenha sido útil agora que se prepara para aprender sobre web scraping e como extrair dados do YouTube!

Sobre o autor
Raluca Penciuc, Desenvolvedor Full-Stack @ WebScrapingAPI
Raluca PenciucDesenvolvedor Full-Stack

Raluca Penciuc é programadora Full Stack na WebScrapingAPI, onde desenvolve scrapers, aperfeiçoa estratégias de evasão e procura formas fiáveis de reduzir a deteção nos sites-alvo.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.