Scraping básico de HTML: los primeros pasos

23 feb 2025

El web scraping puede parecer intimidante al principio, pero como cualquier habilidad, se aprende mejor con práctica directa. En estos tres primeros capítulos, exploraremos los fundamentos de extraer datos de páginas HTML estáticas.

Capítulo 1: El Chad del scraping de HTML

Nuestro recorrido comienza con el escenario más simple posible: extraer texto de una página HTML básica. Este capítulo te introduce a los conceptos centrales de:

  • Hacer solicitudes HTTP para obtener páginas web
  • Cargar contenido HTML en un parser
  • Selección básica del DOM usando selectores CSS

Aunque el ejemplo pueda parecer trivial (¡al fin y al cabo, es solo un “hello world”!), establece la base de todo lo que viene después.

<!-- Example HTML structure -->
<div class="content">
  <p>Some text we want to extract</p>
</div>

Aquí tienes una muestra de con lo que estamos trabajando:

// Basic concepts (not the solution!)
import * as cheerio from 'cheerio';

// Loading HTML content
const $ = cheerio.load(htmlContent);

// Using CSS selectors
const text = $('p').text();  // Selects all <p> tags
const specific = $('.content p').text();  // More specific selection

Capítulo 2: Datos estructurados

Las cosas se vuelven más interesantes cuando nos adentramos en una página de producto simulada de comercio electrónico. Aquí nos encontramos con varios elementos con estructuras similares:

<!-- Example product structure (simplified) -->
<div class="product">
  <h2>Product Name</h2>
  <span class="price">$99.99</span>
  <div class="specs">
    <ul>
      <li>Size: M</li>
      <li>Color: Blue</li>
    </ul>
  </div>
</div>

Al trabajar con datos estructurados como estos, te conviene pensar en:

// Conceptual approach (not the solution!)
$('.product').each((index, element) => {
  // For each product, we might want to:
  // 1. Extract the basic info
  const name = $(element).find('h2').text();

  // 2. Parse nested data
  const specs = $(element).find('.specs li');

  // 3. Structure the output
  const data = {
    name,
    specs: specs.map(/* ... */),
  };
});

Consejo profesional: antes de escribir cualquier código, tómate tiempo para analizar la estructura del HTML. Busca patrones en cómo están organizados los datos: ¿hay nombres de clase consistentes? ¿Cómo se relacionan los elementos padre e hijo?

Capítulo 3: Scraping asistido por IA

¡Ahora es cuando se pone interesante! Aunque los desafíos anteriores nos enseñaron técnicas tradicionales de scraping, el Capítulo 3 introduce un enfoque moderno: web scraping asistido por IA. Nos enfrentamos a un escenario de pesadilla: estructuras HTML inconsistentes, nombres de clase ofuscados y varios patrones de frameworks mezclados entre sí.

Veamos qué hace especial a este desafío:

<!-- Traditional product structure -->
<div data-testid="product-container-1" class="_3xj_item">
  <h2 data-qa="name">Red Sneakers</h2>
  <span data-price-current="5999">$59.99</span>
</div>

<!-- React-style component -->
<div class="ProductCard-root-1a2b3c">
  <div class="ProductCard-title-4d5e6f">Pink Walking Shoes</div>
  <div class="ProductCard-pricing-7g8h9i">$84.99</div>
</div>

<!-- Vue-style template -->
<div data-v-abcdef class="product">
  <h2 data-v-abcdef>Navy Boat Shoes</h2>
  <span data-v-abcdef>$79.99</span>
</div>

Los enfoques tradicionales de scraping tendrían dificultades aquí porque:

  • Los nombres de clase están aleatorizados o son específicos del framework
  • Las estructuras de datos varían entre productos
  • Distintos frameworks usan patrones diferentes
  • El significado semántico se pierde en el marcado

Aquí es donde la IA viene al rescate. En lugar de escribir selectores frágiles, podemos describir lo que queremos en lenguaje natural y dejar que la IA se encargue de la detección de patrones. Los conceptos clave de este capítulo incluyen:

  • Prompt engineering para web scraping
  • Uso de IA para comprender el significado semántico
  • Manejo de estructuras de datos inconsistentes
  • Tratamiento del marcado específico de cada framework
  • Mantenimiento de la consistencia de los datos entre distintos patrones

Aunque la IA no es magia, sobresale en tareas que requieren reconocimiento de patrones y adaptación. Esto la hace especialmente valiosa para hacer scraping de aplicaciones web modernas donde no se pueden garantizar patrones de marcado consistentes.

Una nota sobre el uso de IA

Recuerda que la asistencia de IA no significa soluciones completamente automatizadas. Los mejores resultados surgen de combinar:

  • Definición clara del problema
  • Prompts bien estructurados
  • Validación de datos
  • Supervisión humana

Tu desafío será diseñar prompts que ayuden a la IA a comprender tanto la estructura como la intención de lo que estás tratando de extraer.

¿Listo para combinar el conocimiento tradicional de web scraping con capacidades modernas de IA? ¡Veamos cómo la IA puede ayudar a abordar incluso el HTML más desordenado!

Pistas

  1. Experimenta con distintos selectores CSS:
// Different ways to select elements
$('.class')           // By class
$('#id')             // By ID
$('div > p')         // Direct children
$('div p')           // All descendants
$('[data-type="x"]') // By attribute
  1. Prueba a modificar el formato de salida
  2. Piensa en el manejo de errores y en los casos límite
  3. Considera cómo podría escalar tu solución con conjuntos de datos más grandes

Todo el código que necesitas para empezar está en el repositorio del proyecto. Clónalo, configura tu entorno y ¡empieza a hacer scraping!

git clone https://github.com/jonaylor89/housefly.git
cd housefly
npm install

Inicia los servidores de los capítulos en local: cada capítulo se ejecuta en su propio puerto (3001–3011):

turbo dev

Después, edita tu scraper en exercises/chapter-NN/starter/src/index.ts y valídalo:

npm run validate -- <chapter>

¿Buscas pistas? Ejecuta npm run hint -- <chapter> para obtener orientación progresiva. El HTML fuente de cada desafío está disponible en el directorio apps/chapter{n}/, y las soluciones de referencia están en exercises/chapter-NN/solution/src/. Estudia la estructura, planifica tu enfoque y recuerda: todo experto fue alguna vez principiante.

Recuerda gestionar tus solicitudes de forma responsable:

// Basic error handling example
async function fetchPage(url: string) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.text();
  } catch (error) {
    console.error('Failed to fetch page:', error);
    throw error;
  }
}

¡Feliz scraping!