Extracción de contenido HTML en LLMs con search tool

Este análisis documenta un experimento diseñado para evaluar las capacidades de extracción de contenido estructurado desde páginas HTML con diferentes patrones de maquetación. El objetivo era identificar qué estructuras HTML permiten una extracción exitosa de información y cuáles presentan desafíos para sistemas automatizados de lectura.

Se probaron 15 variantes de páginas HTML, cada una conteniendo información de productos (nombre, descripción y precio) pero estructuradas de formas radicalmente diferentes. Los resultados revelan patrones interesantes sobre cómo los sistemas de extracción interpretan el contenido web.

Cómo funciona la extracción de contenido en LLMs

Cuando los LLMs hacen scraping de páginas web a través de sus herramientas integradas (como web_fetch en Claude, web tool en ChatGPT...), normalmente no ejecutan JavaScript. Es una petición HTTP simple que descarga el HTML estático del servidor. Esto significa que:

  • No se ejecutan scripts de JavaScript
  • No se renderizan estilos CSS
  • No hay contexto visual/renderizado
  • Solo se obtiene el HTML crudo del servidor

Si el sistema usa un navegador sin UI (headless), sí se ejecuta JS y se puede renderizar el DOM dinámico (Puppeteer/Headless Chrome, Playwright). Algunos agentes y scrapers hacen esto explícitamente como Gemini con Googlebot.

Algunos pipelines usan extractores tipo Readability (usado por Firefox Reader View) para detectar el “main content” (basado en heurísticos) y a veces convierten a Markdown con librerías tipo Turndown.js. No obstante, no es universal. Otros (como los basados en APC de Blink, Chromium) generan una representación estructurada del árbol de layout (con texto, imágenes, formularios, geometrías, roles), y luego pueden ofrecer “vistas” como Markdown estructurado o “chunks” de pasajes. No es sólo un “reader mode” simplificado.

Los LLMs no ven el HTML completo. Las heurísticas de extracción filtran lo que consideran "ruido" antes de pasar el contenido al modelo. El proceso básicamente consiste en:

HTML crudo → Algoritmo de detección → Contenido "principal"

Los extractores tipo Readability usan heurísticas documentadas (densidad de texto, link-density, clases/IDs con señales positivas/negativas) y suelen de-priorizar boilerplate (nav/footer/aside), pero no hay una  Además, en pipelines estructurales (APC) la fuente es el layout tree, y el peso proviene de estructura/rol/visibilidad.

Así que el sistema identifica qué es "contenido principal" usando heurísticas como:

  • Densidad de texto en contenedores
  • Eliminación de elementos "no-contenido".
  • Se eliminan o ignoran elementos considerados "ruido":
// Elementos típicamente filtrados como boilerplate
<nav>, <footer>, <aside>, <script>, <style>, 
<iframe>, <meta>, comentarios HTML

Es uno de los motivos por los cuales ninguna web tool que hace fetch dentro de un LLM lee schema.

Nota: En APC, como decíamos antes, esto se hace a partir del layout tree, la presencia/ausencia depende de visibilidad, rol, y si el contenido es "user-visible", pero los scripts se excluyen explícitamente.

Metodología

Cada archivo HTML contenía la misma información básica de un producto ficticio, pero presentada con diferentes patrones de maquetación:

  • Variaciones en el nivel de anidamiento de divs
  • Uso de elementos semánticos vs no semánticos
  • Diferentes posiciones del precio en el DOM
  • Estructuras con listas, blockquotes y elementos de encabezado
  • Texto plano con saltos de línea
  • Estructuras HTML5 semánticas (article, section, header, footer)

El promp era el siguiente:

Entra en cada una de estas URLs, una detrás de otra, y extrae la información del producto. Responde con el nombre del producto, descripción y precio. Si no encuentras algún campo, pon "vacío":
URL1
URL2
...
Por favor, formatea tu respuesta así para cada URL:
URL: [URLN]
- Nombre del producto: [lo que encuentres]
- Descripción: [lo que encuentres]
- Precio: [lo que encuentres]

Este experimento se ha realizado con Gemini, ChatGPT y Claude en todos sus modelos en producción, en modo de chat temporal (sin memoria persistente). Sin embargo, solo se documentan los resultados de Claude porque en las otras IAs la extracción fue exitosa independientemente de la estructura HTML utilizada.

Para evitar posibles alucinaciones y validar los resultados, se realizó una segunda ronda de pruebas revisando cada URL individualmente. En esta ocasión, se solicitó específicamente que devolviera todo el texto visible en la página. Los resultados fueron idénticos a la primera extracción, confirmando que las limitaciones observadas son consistentes y no producto de errores aleatorios del modelo.

Resultados

Categoría 1: DIVs Anidados

Ejemplo 1a: DIVs anidados básicos

<div>
    <div>
        <div>
            <div>
                <div>TechStore Premium</div>
                <div>Monitor UltraWide 34"</div>
                <div>Resolución 3440x1440, 144Hz, panel IPS con HDR400.</div>
                <div>
                    <div>$899.00</div>
                    <button>Comprar ahora</button>
                </div>
            </div>
        </div>
    </div>
</div>

Resultado:

  • Nombre: Monitor UltraWide 34"
  • Descripción: Resolución 3440x1440, 144Hz, panel IPS con HDR400.
  • Precio: vacío

Ejemplo 1b: DIVs anidados con Schema en microdata

<body>
  <div itemscope itemtype="https://schema.org/Product">
    <div>
      <div>
        <div>
          <div>
            <div itemprop="brand" itemscope itemtype="https://schema.org/Brand">
              <span itemprop="name">TechStore Premium</span>
            </div>
            <div itemprop="name">Monitor UltraWide 34"</div>
            <div itemprop="description">
              Resolución 3440x1440, 144Hz, panel IPS con HDR400.
            </div>
            <div itemprop="offers" itemscope itemtype="https://schema.org/Offer">
              <div>
                <meta itemprop="priceCurrency" content="USD">
                <span itemprop="price" content="899.00">$899.00</span>
              </div>
              <button>Comprar ahora</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

Resultado:

  • Igual que el anterior.

Ejemplo 1c: DIVs más anidados

<div>
    <div>
        <div>
            <div>
                <div>
                    <div>TechStore Premium</div>
                    <div>Monitor UltraWide 34"</div>
                    <div>Resolución 3440x1440, 144Hz, panel IPS con HDR400.</div>
                    <div>
                        <div>
                            <div>$899.00</div>
                            <button>Comprar ahora</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Resultado: Idéntico al anterior, el precio no se extrajo.

Ejemplo 1d: Precio fuera del contenedor principal

<div>
    <div>
        <div>
            <div>
                <div>TechStore Premium</div>
                <div>Monitor UltraWide 34"</div>
                <div>Resolución 3440x1440, 144Hz, panel IPS con HDR400.</div>
            </div>
        </div>
    </div>
    <div>$899.00</div>
    <button>Comprar ahora</button>
</div>

Resultado: Precio no extraído, a pesar de estar en el mismo nivel jerárquico que el contenedor principal.

Ejemplo 1f: Precio con símbolo al final

<div>
    <div>
        <div>
            <div>
                <div>TechStore Premium</div>
                <div>Monitor UltraWide 34"</div>
                <div>Resolución 3440x1440, 144Hz, panel IPS con HDR400.</div>
            </div>
        </div>
    </div>
    <div>899.00$</div>
    <button>Comprar ahora</button>
</div>

Resultado: Precio no extraído, independientemente del formato monetario.

Ejemplo 1e: Precio dentro del contenedor

<div>
    <div>
        <div>
            <div>
                <div>TechStore Premium</div>
                <div>Monitor UltraWide 34"</div>
                <div>Resolución 3440x1440, 144Hz, panel IPS con HDR400.</div>
                <div>$899.00</div>
            </div>
        </div>
    </div>
    <button>Comprar ahora</button>
</div>

Resultado:

  • Nombre: Monitor UltraWide 34"
  • Descripción: Resolución 3440x1440, 144Hz, panel IPS con HDR400.
  • Precio: $899.00

Categoría 2: Elementos Semánticos

Ejemplo 2: Lista UL

<ul>
    <li>CameraWorld</li>
    <li>Cámara Mirrorless Z9</li>
    <li>Sensor full frame 45MP, video 8K, estabilización IBIS de 5 ejes.</li>
    <li>$4,599.99</li>
    <li><button>Añadir al carrito</button></li>
</ul>

Resultado: Extracción completa exitosa. Las listas proporcionan una estructura clara y secuencial.

Ejemplo 3: Blockquote

<blockquote>
    <cite>AudioTech Solutions</cite>
    <q>Micrófono Podcast Pro USB</q>
    <p>Patrón cardioide, filtro pop integrado, monitoreo zero-latency.</p>
    <strong>$229.90</strong>
    <button>Ordenar</button>
</blockquote>

Resultado: Extracción completa. Claude no filtra <blockquote> <cite> o <q>.

Ejemplo 4: Headers desordenados

<h6>SmartHome Express</h6>
<h3>Termostato Inteligente WiFi</h3>
<h5>Control desde app, programación automática, ahorro energético del 30%.</h5>
<h4>$179.00</h4>
<h2><button>Comprar producto</button></h2>

Resultado: Extracción completa, a pesar del orden no semántico de los encabezados. Los elementos de encabezado tienen peso suficiente para ser valorados.

Ejemplo 5: Texto plano con BR

<body>
    GamerPro Shop<br>
    Mouse Gaming RGB Elite<br>
    16000 DPI ajustable, 11 botones programables, peso personalizable.<br>
    $89.99<br>
    <button>Agregar</button>
</body>

Resultado: Extracción completa. El texto plano con saltos de línea es fácilmente interpretable como contenido secuencial.

Categoría 3: HTML5 Semántico

Ejemplo 6: Article-Section caótico

<section>
    <article>
        <section>FitTech Wearables</section>
        <article>Banda Fitness Pro 6</article>
    </section>
    <aside>Medición SpO2, sueño, 120 modos deportivos, batería 14 días.</aside>
    <article>
        <section>$149.50</section>
        <button>Adquirir ahora</button>
    </article>
</section>

Resultado:

  • Nombre: Banda Fitness Pro 6
  • Descripción: vacío
  • Precio: $149.50

La descripción estaba en un elemento aside, que parece haberse filtrado.

Ejemplo 7: Article con header y footer

<article>
    <header>
        <p>ElectroGaming Store</p>
        <h1>Consola Retro Arcade Plus</h1>
    </header>
    <p>Emulador con 10,000 juegos clásicos, HDMI 4K, 2 controles inalámbricos incluidos.</p>
    <footer>
        <span>$349.99</span>
        <button>Comprar ahora</button>
    </footer>
</article>

Resultado:

  • Nombre: Consola Retro Arcade Plus
  • Descripción: Emulador con 10,000 juegos clásicos, HDMI 4K, 2 controles inalámbricos incluidos.
  • Precio: vacío

El precio dentro del footer no fue extraído aún siendo válido en esa posición.

Ejemplo 8: Article simple

<article>
    <h1>Tablet Pro Max 12.9"</h1>
    <p>TechDigital Corporation</p>
    <p>Pantalla OLED 120Hz, chip M2, 8GB RAM, compatible con stylus, teclado magnético.</p>
    <p>Precio: <strong>$1,199.00</strong></p>
    <button>Añadir al carrito</button>
</article>

Resultado: Extracción completa exitosa. Estructura simple y clara dentro de un article.

Categoría 4: HTML Tradicional

Ejemplo 9a: HTML tradicional con H3

<div>
    <h3>Smartphone Galaxy Ultra 5G</h3>
    <p><strong>Marca:</strong> PhoneTech Global</p>
    <p><strong>Descripción:</strong> Cámara 200MP con zoom 10x, batería 5000mAh, pantalla AMOLED 6.8", procesador Snapdragon 8 Gen 3.</p>
    <p><strong>Precio:</strong> $999.00</p>
    <button type="button">Comprar ahora</button>
</div>

Resultado:

  • Nombre: vacío
  • Descripción: Cámara 200MP con zoom 10x, batería 5000mAh, pantalla AMOLED 6.8", procesador Snapdragon 8 Gen 3.
  • Precio: $999.00

El nombre del producto en H3 no fue identificado como tal, posiblemente su heurística ignore el H3 dentro de un div.

Ejemplo 9b: HTML Tradicional con H2 ❌

<div>
    <p>SportTech Equipment</p>
    <h2>Bicicleta Eléctrica Mountain Pro</h2>
    <p>Motor 750W, batería 48V, autonomía 80km, suspensión delantera, frenos hidráulicos.</p>
    <p>Precio: $2,299.00</p>
    <button>Comprar ahora</button>
</div>

Resultado:

  • Nombre: vacío
  • Descripción: Motor 750W, batería 48V, autonomía 80km, suspensión delantera, frenos hidráulicos.
  • Precio: $2,299.00

Similar al caso anterior, el H2 no fue identificado como nombre del producto posiblemente por el motivo anterior.

Ejemplo 9c: HTML tradicional con H1

<div>
    <p>HomeComfort Store</p>
    <h1>Robot Aspiradora Smart Clean X9</h1>
    <p>Navegación láser LiDAR, mopa integrada, vaciado automático, control por app.</p>
    <span>$649.99</span>
    <button>Añadir al carrito</button>
</div>

Resultado: Extracción completa.

Análisis de patrones y conclusiones

Este análisis tiene implicaciones importantes para desarrolladores web que desean que su contenido sea correctamente interpretado por sistemas automatizados. Se han revelado varios patrones sobre qué estructuras HTML facilitan la extracción de contenido:

  1. Cohesión en el contenedor: El contenido relacionado debe mantener el mismo nivel de anidamiento dentro de un contenedor común. Cuando elementos como el precio se colocan en niveles de anidamiento adicionales o fuera del contenedor principal, el sistema de extracción no los asocia correctamente con el resto del producto. La extracción falla no por estar en un div, sino por la ruptura de la cohesión estructural.
  2. Jerarquía semántica: Los elementos con mayor peso semántico (H1, article, listas) son reconocidos más fácilmente. El H1 fue identificado como nombre de producto, mientras que H2 y H3 no lo fueron. Esto sugiere que el sistema prioriza los elementos de mayor jerarquía en el documento.
  3. Simplicidad estructural: Las estructuras simples y directas (texto plano con BR, listas lineales) tuvieron extracción exitosa.
  4. Elementos semánticos específicos: Ciertos elementos HTML5 parecen tener un tratamiento especial:
    • footer: Su contenido no se extrae, probablemente porque se considera metainformación o contenido secundario aunque esté dentro de un article.
    • aside: También parece filtrarse, tratándose como contenido tangencial.
    • header: Su contenido sí se procesa.

      Aunque otras IAs como Gemini y ChatGPT no presentaron problemas de extracción en este experimento, esto no significa que podamos ignorar la estructura HTML. La forma en que el "reader mode" convierte el contenido a texto plano tiene un significado semántico que se deriva directamente del DOM. Una página bien estructurada facilita el contexto y la comprensión del contenido, independientemente del modelo que lo procese.

      El hecho de que algunos modelos compensen mejor las deficiencias estructurales no elimina la responsabilidad de escribir HTML correcto. Una estructura semántica clara:

      • Reduce la ambigüedad interpretativa
      • Facilita el contexto para todos los sistemas de extracción
      • Mejora la accesibilidad para usuarios con lectores de pantalla
      • Garantiza una extracción más consistente y predecible por cualquier sistema de extracción, ya sea un LLM o un buscador.

      En definitiva, que tu contenido "funcione" con algunas herramientas no significa que esté bien estructurado. El HTML semántico correcto es una inversión en robustez y compatibilidad futura.

      Relacionado

      Agentes web y la importancia del HTML semántico y accesible

      Tráfico agéntico: así navegan los agentes de IA y qué tienes que saber tú

       

      Natzir Turrado 06 noviembre 2025

      Compartir

      Facebook Linkedin Twitter

      Otros artículos

      Los algoritmos de Google al descubierto. Cómo funciona el buscador según documentos filtrados

      En este artículo nos adentramos en el funcionamiento interno de Google, una herramienta que todos usamos a diario pero que pocos comprendemos realmente. A raíz de la reciente filtración de documentos en un juicio antimonopolio contra Google, tenemos una gran oportunidad para explorar los algoritmos de Google. De algunos de ellos ya teníamos información, pero […]

      Leer más

      El CTR afecta al SEO, pero ¿por qué no se puede manipular artificialmente?

      Últimamente hay mucho ruido con el tema de CTR y su impacto en el SEO, que si manipular el CTR funciona, que parece que funciona o simplemente no funciona… Para los neófitos, el CTR (Click-through rate) en SEO es un ratio que mide la eficacia de un resultado en la página de resultados de Google (SERP). Es la división […]

      Leer más