Volver al blog
Guías
Raluca PenciucLast updated on Mar 31, 20269 min read

Cómo extraer datos de YouTube como un profesional: una guía completa

Cómo extraer datos de YouTube como un profesional: una guía completa

¿Necesitas datos de una página web, pero las API disponibles no te dan la solución que buscas? El web scraping es la respuesta que estabas buscando. Con el web scraping, puedes extraer datos de una página web de forma más completa y flexible.

En este artículo, nos adentraremos en el mundo del web scraping analizando en detalle cómo extraer datos de YouTube, una de las plataformas de intercambio de vídeos más populares. Aunque YouTube ofrece una API para acceder a los datos, el web scraping puede ofrecer una mayor variedad de opciones para extraer datos de los canales de YouTube.

Comenzaremos configurando un entorno de desarrollo y repasando los requisitos previos para el web scraping, para luego pasar al proceso real de cómo extraer datos de YouTube. A lo largo del artículo, te daremos consejos para mejorar tus habilidades de web scraping y analizaremos por qué utilizar un scraper profesional puede ser una mejor opción que crear uno propio.

Al final de este artículo, contarás con los conocimientos y habilidades necesarios para extraer datos de YouTube de forma eficaz, ¡como un profesional!

Requisitos previos

Lo primero es lo primero: debes asegurarte de que tienes Node.js instalado en tu equipo. Si aún no lo tienes, dirígete a la página web oficial de Node.js y sigue las instrucciones para tu sistema operativo específico. Es importante que descargues la versión de soporte a largo plazo (LTS) para asegurarte de que dispones de una versión estable y compatible.

A continuación, tendrás que instalar el Node.js Package Manager (NPM). Este debería venir automáticamente con la instalación de Node.js, pero siempre es bueno comprobarlo.

En cuanto al entorno de programación, puedes utilizar el IDE que prefieras. En este tutorial usaré Visual Studio Code porque es flexible y fácil de usar, pero cualquier IDE servirá. Simplemente crea una nueva carpeta para tu proyecto y abre un terminal. Ejecuta el siguiente comando para configurar un nuevo proyecto de Node.js:

npm init -y

Esto creará un archivo package.json predeterminado para tu proyecto. Puedes modificar este archivo en cualquier momento para adaptarlo a tus necesidades.

Ahora es el momento de instalar TypeScript y las definiciones de tipos para Node.js. TypeScript es una opción muy popular entre la comunidad de JavaScript debido a su tipado estático opcional, que ayuda a evitar errores de tipos en tu código. Para instalarlo, ejecuta el siguiente comando:

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

Para verificar que la instalación se ha realizado correctamente, puedes ejecutar el siguiente comando:

npx tsc --version

Por último, tendrás que crear un archivo de configuración tsconfig.json en la raíz del directorio de tu proyecto. Este archivo define las opciones del compilador para tu proyecto. Si quieres saber más sobre este archivo y sus propiedades, consulta la documentación oficial de TypeScript.

Como alternativa, puedes copiar y pegar el siguiente código en tu archivo tsconfig.json:

{

   "compilerOptions": {

       "module": "commonjs",

       "esModuleInterop": true,

       "target": "es2017",

       "moduleResolution": "node",

       "sourceMap": true,

       "outDir": "dist"

   },

   "lib": ["es2015"]

}

Para el proceso de scraping, utilizaré Puppeteer, una biblioteca de navegador sin interfaz gráfica para Node.js que permite controlar un navegador web e interactuar con sitios web mediante programación. Para instalar Puppeteer, ejecuta el siguiente comando:

npm install puppeteer

Extracción de los datos

Para esta guía, voy a extraer datos de un canal de YouTube con tutoriales relacionados con DevOps: https://www.youtube.com/@TechWorldwithNana/videos. Los datos que me interesan en particular son:

  • el avatar del canal
  • el nombre del canal
  • el nombre de usuario del canal
  • el número de suscriptores del canal
  • los títulos de todos los vídeos
  • el número de visualizaciones de todos los vídeos
  • la miniatura de todos los vídeos
  • la URL de todos los vídeos

Incluiré capturas de pantalla para cada sección y utilizaré selectores CSS para localizar los datos en el DOM. Este es el método más sencillo y directo, a menos que el sitio web de destino sea conocido por tener una estructura DOM inestable.

Si eres nuevo en el uso de selectores CSS, echa un vistazo a esta completa hoja de referencia que te permitirá ponerte en marcha en un santiamén.

Empecemos creando una carpeta src y el archivo index.ts donde escribiremos el código. Ahora abramos un navegador y accedamos a la 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 facilitar la depuración visual, abriré el navegador en modo no headless. Si tienes intención de ampliar tu caso de uso a gran escala, te recomiendo que eches un vistazo al modo headless.

Para ejecutar el script, primero debes compilarlo y, a continuación, ejecutar el archivo JavaScript generado. Para facilitar las cosas, podemos definir un script en el archivo package.json que se encargue de ambos pasos por nosotros. Simplemente edita la sección scripts de tu archivo package.json de la siguiente manera:

"scripts": {

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

},

Ahora, todo lo que tienes que hacer para ejecutar tu código es ejecutar el siguiente comando:

npm run test

Desde la primera ejecución, nos encontramos con un primer problema: el cuadro de diálogo de consentimiento de cookies a pantalla completa que nos impide acceder a los datos.

Por suerte, es visible dentro del área de visualización, por lo que podemos usar las Herramientas de desarrollador para encontrar su identificador y hacer clic en él.

También añadimos un tiempo de espera adicional para dejar que se complete la navegación. El código tendrá este aspecto:

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

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

await page.waitForTimeout(10 * 1000)

Información del canal

En la captura de pantalla siguiente podemos ver resaltadas las secciones que contienen los datos del canal que queremos extraer.

Una buena regla general para localizar fácilmente los elementos HTML es elegir selectores CSS únicos. Por ejemplo, para extraer el avatar del canal, elegiré el elemento HTML personalizado yt-img-shadow con el id avatar. A continuación, extraeré el atributo src de su elemento hijo 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 el nombre del canal, tenemos el contenido de texto del elemento yt-formatted-string con el id text.

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

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

    return el ? el.textContent : null;

});

console.log(channelName)

Para obtener el nombre de usuario del canal, localizaremos el elemento yt-formatted-string con el id channel-handle y extraeremos su contenido de texto.

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

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

    return el ? el.textContent : null;

});

console.log(channelHandle)

Y, por último, para obtener el número de suscriptores del canal, solo tenemos que acceder al elemento yt-formatted-string con el id subscriber-count y obtener su contenido de texto.

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

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

    return el ? el.textContent : null;

});

console.log(subscriberCount)

Al ejecutar el script de nuevo, deberías ver el siguiente resultado:

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

TechWorld with Nana

@TechWorldwithNana

709K subscribers

Datos del vídeo

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.

Evita que te bloqueen

Aunque la guía hasta este punto parecía sencilla, hay múltiples retos a los que suelen enfrentarse los rastreadores web. YouTube, en particular, implementa muchas técnicas antibot para evitar que los scripts automatizados extraigan sus datos.

Algunas de estas técnicas son:

  • CAPTCHAs: resolver CAPTCHAs puede llevar mucho tiempo y resultar difícil para un scraper, lo que puede servir como elemento disuasorio para los bots.
  • Retos de JavaScript: pueden incluir tareas como resolver problemas matemáticos, completar un CAPTCHA o encontrar un elemento específico en la página. Un bot que no sea capaz de completar el reto será detectado y, potencialmente, bloqueado.
  • Comprobaciones del agente de usuario: YouTube puede comprobar la cadena del agente de usuario de las solicitudes entrantes para ver si proceden de un navegador o de un rastreador. Si la cadena del agente de usuario no se reconoce como un navegador válido, la solicitud puede ser bloqueada.
  • Bloqueo de IP: YouTube puede bloquear las solicitudes procedentes de determinadas direcciones IP que se sabe que están asociadas a bots o a actividades de scraping.
  • Honeypots: YouTube puede utilizar honeypots, que son elementos ocultos en la página que solo son visibles para los bots. Si se detecta que un bot interactúa con un honeypot, puede identificarse y bloquearse.

Abordar cada uno de estos problemas puede aumentar significativamente la complejidad y el coste de tu código de scraper. Aquí es donde las API de scraping desempeñan un papel importante, ya que gestionan estos problemas de forma predeterminada y están disponibles a un precio más bajo.

WebScrapingAPI es un ejemplo de este tipo de servicio. Ofrece potentes funciones para evitar las técnicas de detección de bots y extraer con precisión los datos que necesitas.

Podemos probar rápidamente WebScrapingAPI instalando el SDK de Node.js en nuestro pequeño proyecto:

npm i webscrapingapi

Ahora visita la página de inicio para registrarte y crear una cuenta, lo que te proporcionará automáticamente tu clave API y una prueba gratuita. La clave API se encuentra en el panel de control y la utilizarás para autenticar tus solicitudes a la API:

¡Y eso es todo, ya puedes empezar 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");

Hemos adaptado el algoritmo y los selectores CSS descritos anteriormente a la API. El parámetro «js_instructions» se encargará de la ventana de cookies, haciendo clic en el botón «Aceptar todo». Por último, el parámetro «extract_rules» se encargará de la extracción de datos.

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

}

A continuación, justo antes de enviar la solicitud, recuerda ajustar también la lógica de desplazamiento. Esto será ligeramente diferente, ya que le indicamos a la API que se desplace hasta la tercera fila de vídeos 10 veces.

Conclusión

En este artículo, hemos explorado el apasionante campo del web scraping y hemos aprendido a extraer datos de YouTube utilizando Node.js y Puppeteer. Hemos cubierto la configuración necesaria para el web scraping, así como el proceso de extracción de datos de los canales de YouTube.

El web scraping puede ser una herramienta increíblemente útil para acceder a datos de sitios web. Sin embargo, es importante tener en cuenta los diversos retos y consideraciones que conlleva. Estos pueden incluir CAPTCHAs, contenido dinámico, limitación de velocidad o cambios en el sitio web.

Si estás pensando en extraer datos de YouTube o de cualquier otro sitio web, es esencial sopesar los pros y los contras y determinar si el web scraping es la mejor solución para tus necesidades. En algunos casos, utilizar una API o comprar datos de una fuente de confianza puede ser una opción más adecuada que el scraping.

Independientemente del enfoque que elijas, es fundamental respetar los términos de servicio y las leyes de derechos de autor que se aplican a los datos a los que accedes. Y si decides extraer datos de YouTube, recuerda utilizar un extractor profesional para asegurarte de obtener datos precisos y actualizados de forma segura y eficiente.

¡Espero que este artículo te haya resultado útil en tu camino para aprender sobre el web scraping y cómo extraer datos de YouTube!

Acerca del autor
Raluca Penciuc, Desarrollador full-stack @ WebScrapingAPI
Raluca PenciucDesarrollador full-stack

Raluca Penciuc es desarrolladora full stack en WebScrapingAPI, donde se dedica a crear rastreadores, mejorar las técnicas de evasión y buscar formas fiables de reducir la detección en los sitios web de destino.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.