Web Scraping y LLMs

Guía de Python Web Scraping y Extracción para LLM (2026)

Respuesta Rápida: En 2026, los python web scraping projects para alimentar LLMs requieren una arquitectura de dos fases: renderizado headless asíncrono (Playwright o Crawl4AI) junto con poda algorítmica del DOM (eliminando SVG, scripts y menús) antes de la inferencia. Para datos estructurados, los esquemas Pydantic con Instructor garantizan JSON determinista reduciendo costes de tokens en un 75-88%.


1. Introducción: Web Scraping en la era de los LLMs y Agentes Autónomos

Los agentes autónomos de IA y los motores RAG dependen críticamente de contexto web fresco y verificado. Aunque modelos como Claude 3.7 Sonnet, DeepSeek V3/R1 y GPT-4o ofrecen contextos de hasta 2 millones de tokens, alimentar HTML sin procesar en los mecanismos de atención Transformer representa uno de los antipatrones más costosos de la ingeniería moderna.

Históricamente, para scrape website python, la norma era usar requests con BeautifulSoup o arañas de Scrapy. Hoy en día, la web está dominada por aplicaciones SPA dinámicas en Next.js, React y Vue, resguardadas por WAFs como Cloudflare Turnstile, DataDome y Akamai.

El objetivo del scraping ha evolucionado:

  • Scraping Tradicional (2015–2023): Extraer campos rígidos a bases de datos relacionales mediante selectores XPath o CSS.
  • Scraping para Agentes y LLMs (2026): Procesar páginas dinámicas, podar ruido innecesario, preservar Markdown semántico y extraer JSON fuertemente tipado mediante esquemas Pydantic.

2. Comparativa de Frameworks: BeautifulSoup vs Scrapy vs Playwright vs Crawl4AI

Dimensión BeautifulSoup4 + Requests Scrapy (Twisted/AsyncIO) Raw Playwright (Async Python) Crawl4AI (v0.9.x+)
Caso Principal Scripts ligeros y HTML estático Extracción masiva distribuida SPAs dinámicas e interacciones JS Agentes de IA, RAG y extracción LLM
Ejecución JS Ninguna Ninguna (requiere Scrapy-Playwright) Motor completo Chromium y WebKit Chromium optimizado para LLMs
Rendimiento ~15-25 req/s por worker ~150-300 req/s por spider ~5-12 pág/s por 16GB RAM ~25-45 pág/s (reutilización)
Consumo de Memoria Mínimo (~40MB) Bajo (~120MB) Alto (150-350MB por contexto) Moderado (~80-140MB por pestaña)
Salida Markdown Requiere librería externa Pipeline personalizado Integración manual Markdown nativo optimizado para LLM
Limpieza de DOM Código manual Selectores manuales Evaluación CDP manual PruningContentFilter y BM25 nativo
Evasión Anti-Bot Básica (solo User-Agent) Proxies en middleware Avanzada (playwright-stealth) Stealth integrado y TLS emulado
Soporte Pydantic Ninguno ItemLoaders Ninguno Motor nativo de esquemas Pydantic

3. Economía del Scraping para LLMs: Poda de Ruido DOM

El HTML sin procesar desperdicia entre el 85% y el 95% de los tokens en clases CSS, scripts analíticos y navegación.

Impacto financiero en 50.000 páginas diarias (GPT-4o a $2.50 / 1M tokens)

  • Tokens diarios en HTML bruto: 50.000 × 55.000 = 2.750 millones de tokens
  • Tokens diarios en Markdown limpio: 50.000 × 4.200 = 210 millones de tokens
  • Ahorro diario: (2.750 - 210) × $2.50 = $6.350,00 / día
  • Ahorro mensual: $190.500,00 / mes

4. Implementación en Python: Async Playwright y Selectolax

# clean_scraper.py
import asyncio
from playwright.async_api import async_playwright
from selectolax.parser import HTMLParser
import markdownify

async def scrape_clean_markdown(url: str) -> str:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True, args=["--no-sandbox"])
        page = await browser.new_page()
        await page.goto(url, wait_until="networkidle", timeout=30000)
        raw_html = await page.content()
        await browser.close()

    parser = HTMLParser(raw_html)
    for tag in ["script", "style", "svg", "noscript", "header", "footer", "nav", "aside"]:
        for node in parser.css(tag):
            node.decompose()

    main = parser.css_first("main, article, #content") or parser.css_first("body")
    return markdownify.markdownify(main.html if main else parser.html, heading_style="ATX")

5. Extracción con Crawl4AI

# crawl4ai_pipeline.py
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
from crawl4ai.content_filter_strategy import PruningContentFilter

async def run_crawl4ai(url: str) -> str:
    async with AsyncWebCrawler(config=BrowserConfig(headless=True)) as crawler:
        config = CrawlerRunConfig(
            cache_mode=CacheMode.BYPASS,
            content_filter=PruningContentFilter(threshold=0.48),
            wait_until="networkidle"
        )
        res = await crawler.arun(url=url, config=config)
        return res.markdown

6. Extracción Estructurada con Pydantic e Instructor

# pydantic_extractor.py
import os
from typing import List, Optional
from pydantic import BaseModel, Field
import instructor
from openai import OpenAI

class TechSpec(BaseModel):
    name: str = Field(description="Característica técnica")
    supported: bool = Field(description="Soporte nativo")

class ProductInfo(BaseModel):
    product_name: str
    price_usd: Optional[float] = None
    specs: List[TechSpec]

def extract_data(clean_md: str) -> ProductInfo:
    client = instructor.from_openai(OpenAI(api_key=os.environ["OPENAI_API_KEY"]))
    return client.chat.completions.create(
        model="gpt-4o-mini",
        response_model=ProductInfo,
        messages=[{"role": "user", "content": clean_md}],
        temperature=0.0
    )

7. Evasión de WAF con curl_cffi

# stealth_requester.py
from curl_cffi import requests

def fetch_stealth(url: str, proxy: str = None) -> str:
    proxies = {"http": proxy, "https": proxy} if proxy else None
    return requests.get(url, impersonate="chrome124", proxies=proxies, timeout=15).text

8. Desglose de Costes (Prueba de 100.000 Páginas)

Componente Playwright Bruto Playwright + Selectolax Crawl4AI Async Firecrawl Cloud
Cómputo (AWS) $48.00 $22.00 $16.00 $0.00
Proxies Residenciales $120.00 $32.00 $30.00 Incluido
Inferencia LLM (GPT-4o) $13.750.00 $1.050.00 $975.00 $825.00
Coste Total $13.918.00 $1.104.00 $1.021.00 $1.024.00

9. Conclusiones y Recomendaciones de Ingeniería

  1. Estrategia Escalonada: Usar curl_cffi para HTML estático y Crawl4AI para SPAs interactivas.
  2. Poda Rigurosa: Nunca enviar HTML bruto al modelo; asegurar al menos un 80% de compresión.
  3. Contratos Pydantic: Emplear instructor para validación y corrección automática.
  4. Desacoplar Ingesta: Separar el crawling de la inferencia mediante colas asíncronas.
← Todos los Artículos
0 / 4