CrawlForge
InicioPlaygroundCasos de usoIntegracionesPreciosDocumentaciónBlog
Guía de web scraping con LlamaIndex y CrawlForge MCP
Tutorials
Volver al blog
Tutoriales

Guía de web scraping con LlamaIndex y CrawlForge MCP

C
CrawlForge Team
Equipo de Ingeniería
14 de abril de 2026
11 min de lectura

En esta página

LlamaIndex es el framework de referencia para RAG en producción, pero viene con readers de HTML que se desmoronan en sitios con mucho JavaScript y páginas protegidas por Cloudflare. Cámbialos por CrawlForge y tu pipeline de LlamaIndex manejará cualquier URL: HTML estático, SPA o muro anti-bot.

Python
from llama_index.core import Document
from crawlforge_llamaindex import CrawlForgeReader

reader = CrawlForgeReader(api_key="cf_live_your_key")
docs: list[Document] = reader.load_data(urls=["https://docs.stripe.com/api"])

Esta guía muestra cómo usar el web scraping con LlamaIndex y CrawlForge como tu fuente de datos: desde loaders de una sola página hasta pipelines RAG completos y herramientas de agentes.

Índice

  • Por qué LlamaIndex necesita un mejor lector web
  • Requisitos previos
  • Paso 1: Instala las dependencias
  • Paso 2: Crea un lector de CrawlForge
  • Paso 3: Indexa páginas web en vivo
  • Paso 4: Consulta el índice
  • Ejemplo completo: RAG de docs con actualizaciones en vivo
  • Avanzado: herramientas de CrawlForge para agentes de LlamaIndex
  • Solución de problemas
  • Preguntas frecuentes

Por qué LlamaIndex necesita un mejor lector web

El SimpleWebPageReader y el BeautifulSoupWebReader integrados de LlamaIndex están bien para entradas de blog estáticas, pero fallan en:

  • Contenido renderizado con JavaScript (apps de React, Vue, Angular)
  • Páginas protegidas por Cloudflare / DataDome / Akamai (la mayoría de docs SaaS)
  • Sitios que devuelven 403 a User-Agents genéricos
  • Páginas donde el contenido principal está dentro de un hermano <main>, no extraíble de forma trivial

CrawlForge resuelve los cuatro casos. Su herramienta extract_content usa un algoritmo de legibilidad afinado para páginas de artículos, docs y productos. stealth_mode maneja el anti-bot. scrape_with_actions ejecuta JavaScript. Las 26 herramientas devuelven texto o markdown limpio listo para chunking. Para entender por qué esto importa en RAG, consulta nuestra guía de pipelines RAG.

Requisitos previos

  • Python 3.9+ -- python --version
  • LlamaIndex -- pip install llama-index-core llama-index-readers-web
  • Cuenta de CrawlForge -- gratis en crawlforge.dev/signup, 1.000 credits incluidos
  • API key de OpenAI o Anthropic para las llamadas al LLM de LlamaIndex (o usa cualquier proveedor compatible)

Paso 1: Instala las dependencias

Bash
pip install llama-index-core llama-index-embeddings-openai requests

Exporta tus claves:

Bash
export CRAWLFORGE_API_KEY="cf_live_your_key_here"
export OPENAI_API_KEY="sk-..."

Paso 2: Crea un lector de CrawlForge

Los readers de LlamaIndex heredan de BaseReader y devuelven objetos Document. Aquí tienes un reader mínimo que envuelve el endpoint extract_content de CrawlForge:

Python
# crawlforge_reader.py
import os
from typing import List, Optional
import requests
from llama_index.core.readers.base import BaseReader
from llama_index.core.schema import Document


class CrawlForgeReader(BaseReader):
    """LlamaIndex reader that uses CrawlForge for web scraping."""

    BASE_URL = "https://crawlforge.dev/api/v1/tools"

    def __init__(self, api_key: Optional[str] = None, use_stealth: bool = False):
        self.api_key = api_key or os.environ["CRAWLFORGE_API_KEY"]
        self.use_stealth = use_stealth

    def load_data(self, urls: List[str]) -> List[Document]:
        documents = []
        tool = "stealth_mode" if self.use_stealth else "extract_content"

        for url in urls:
            response = requests.post(
                f"{self.BASE_URL}/{tool}",
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json",
                },
                json={
                    "url": url,
                    "options": {"format": "markdown"},
                },
                timeout=30,
            )
            response.raise_for_status()
            data = response.json()

            documents.append(
                Document(
                    text=data.get("content", ""),
                    metadata={
                        "source": url,
                        "title": data.get("title"),
                        "scraped_at": data.get("scraped_at"),
                    },
                )
            )

        return documents

Coste: 2 credits por URL con extract_content, 5 credits con stealth_mode.

Paso 3: Indexa páginas web en vivo

Conecta el reader a un pipeline estándar de LlamaIndex:

Python
# build_index.py
from llama_index.core import VectorStoreIndex
from crawlforge_reader import CrawlForgeReader

reader = CrawlForgeReader()
docs = reader.load_data(urls=[
    "https://docs.stripe.com/api/charges/create",
    "https://docs.stripe.com/api/payment_intents/create",
    "https://docs.stripe.com/api/refunds/create",
])

index = VectorStoreIndex.from_documents(docs)
index.storage_context.persist(persist_dir="./storage/stripe_docs")

Ahora tienes un índice persistido de la API de Stripe creado a partir de docs en vivo. Coste: 6 credits (3 URLs x 2).

Paso 4: Consulta el índice

Python
# query_index.py
from llama_index.core import StorageContext, load_index_from_storage

storage = StorageContext.from_defaults(persist_dir="./storage/stripe_docs")
index = load_index_from_storage(storage)

query_engine = index.as_query_engine()
response = query_engine.query(
    "What are the required fields to create a Charge in Stripe's API?"
)
print(response)
# -> "To create a Charge, you must provide amount (integer in cents) and
#     currency (three-letter ISO code). Additionally you need a source
#     (payment method) or customer."

Ejemplo completo: RAG de docs con actualizaciones en vivo

Júntalo todo: un RAG de docs de Stripe que se refresca cada noche:

Python
# docs_rag.py
import os
from datetime import datetime
from llama_index.core import VectorStoreIndex, StorageContext, load_index_from_storage
from crawlforge_reader import CrawlForgeReader

PERSIST_DIR = "./storage/stripe_docs"
TARGET_URLS = [
    "https://docs.stripe.com/api/charges/create",
    "https://docs.stripe.com/api/payment_intents/create",
    "https://docs.stripe.com/api/refunds/create",
    "https://docs.stripe.com/api/customers/create",
    "https://docs.stripe.com/api/subscriptions/create",
]


def refresh_index() -> VectorStoreIndex:
    """Re-scrape sources and rebuild the index."""
    reader = CrawlForgeReader()
    docs = reader.load_data(urls=TARGET_URLS)
    index = VectorStoreIndex.from_documents(docs)
    index.storage_context.persist(persist_dir=PERSIST_DIR)
    print(f"Indexed {len(docs)} docs at {datetime.utcnow().isoformat()}Z")
    return index


def load_index() -> VectorStoreIndex:
    """Load the persisted index from disk."""
    storage = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
    return load_index_from_storage(storage)


def ask(question: str) -> str:
    index = load_index() if os.path.exists(PERSIST_DIR) else refresh_index()
    return str(index.as_query_engine().query(question))


if __name__ == "__main__":
    # Refresh once a day in a cron job: python docs_rag.py --refresh
    import sys
    if "--refresh" in sys.argv:
        refresh_index()
    else:
        print(ask("How do I create a refund for a charge?"))

Coste del refresco nocturno: 10 credits (5 URLs x 2). En 30 días son 300 credits, holgadamente dentro del plan gratuito.

Avanzado: herramientas de CrawlForge para agentes de LlamaIndex

El sistema de agentes de LlamaIndex acepta definiciones de FunctionTool arbitrarias. Envuelve las llamadas a CrawlForge como herramientas y tu agente podrá hacer scraping bajo demanda:

Python
# crawlforge_tools.py
from llama_index.core.tools import FunctionTool
from crawlforge_reader import CrawlForgeReader


def scrape_url(url: str) -> str:
    """Scrape a URL and return its main content as markdown."""
    reader = CrawlForgeReader()
    docs = reader.load_data(urls=[url])
    return docs[0].text if docs else ""


def search_and_scrape(query: str, n: int = 3) -> list[str]:
    """Search the web and return content from the top N results."""
    import os, requests
    resp = requests.post(
        "https://crawlforge.dev/api/v1/tools/search_web",
        headers={"Authorization": f"Bearer {os.environ['CRAWLFORGE_API_KEY']}"},
        json={"query": query, "limit": n},
        timeout=30,
    ).json()
    urls = [r["url"] for r in resp.get("results", [])]
    reader = CrawlForgeReader()
    return [d.text for d in reader.load_data(urls=urls)]


scrape_tool = FunctionTool.from_defaults(fn=scrape_url)
search_tool = FunctionTool.from_defaults(fn=search_and_scrape)

Después pasa [scrape_tool, search_tool] a cualquier agente de LlamaIndex:

Python
from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI

agent = ReActAgent.from_tools(
    tools=[scrape_tool, search_tool],
    llm=OpenAI(model="gpt-4o-mini"),
    verbose=True,
)

response = agent.chat(
    "Research the current state of Anthropic's MCP protocol adoption in 2026. "
    "Cite at least 3 sources."
)
print(response)

Desglose del coste en credits

OperaciónHerramientaCredits
Ingerir una página estáticaextract_content2
Ingerir una página con mucho JSscrape_with_actions5
Ingerir una protegida por Cloudflarestealth_mode5
Búsqueda + scraping del agente (3 URLs)search_web + 3x extract_content11
Deep research completodeep_research10

Solución de problemas

Document.text vacío en algunas URLs -- La página probablemente requiere JavaScript. Instancia con use_stealth=True o crea una variante del reader que llame a scrape_with_actions.

requests.exceptions.HTTPError: 429 -- Estás alcanzando el límite de velocidad de CrawlForge. Añade reintentos con backoff o divide las cargas masivas en lotes de 10 URLs.

La indexación de LlamaIndex es lenta -- Procesa en lotes las llamadas a tu reader con concurrent.futures.ThreadPoolExecutor (vinculado a E/S, el GIL no es un bloqueo). Lo habitual es un aumento de velocidad de 10x en 50+ URLs.

Faltan metadatos del Document -- El endpoint scrape_structured de CrawlForge no rellena title igual que lo hace extract_content. Usa extract_content para la ingesta de RAG; usa scrape_structured solo para la extracción de campos tipados.

El coste de embeddings se dispara -- LlamaIndex vuelve a generar embeddings en cada llamada a VectorStoreIndex.from_documents. Persiste con index.storage_context.persist() y carga con load_index_from_storage() para evitar trabajo repetido.

Próximos pasos

  • Lee la guía de pipelines RAG para patrones de recuperación de extremo a extremo
  • Explora otros frameworks en nuestra entrada sobre integración con LangChain
  • Consulta los docs de primeros pasos para la API REST completa
  • Compara proveedores de scraping en alternativa a Firecrawl

Empieza gratis con 1.000 credits en crawlforge.dev/signup. No se requiere tarjeta de crédito.

Pruébalo tú mismo — sin necesidad de registrarte

Ejecuta cualquiera de las 27 herramientas de scraping y extracción de CrawlForge en el playground y luego empieza gratis con 1,000 credits.

1,000 credits gratis • Se recargan cada mes • No se requiere tarjeta de crédito

Etiquetas

LlamaIndexweb-scrapingRAGPythontutorialvector-searchAI-agents

Sobre el autor

C

CrawlForge Team

Equipo de Ingeniería

Construimos el MCP server de web scraping más completo. Creamos herramientas que ayudan a los desarrolladores a extraer, analizar y transformar datos web para aplicaciones de IA.

Mantente al día con los últimos artículos

Recibe tutoriales, novedades del producto y consejos de web scraping en tu bandeja de entrada.

Sin spam. Cancela tu suscripción cuando quieras.

Ponlo en práctica

Prueba las herramientas de CrawlForge en cualquier URL — gratis, sin registro.

En esta página

Frequently Asked Questions

¿Por qué no usar los readers web integrados de LlamaIndex?+

SimpleWebPageReader y BeautifulSoupWebReader funcionan con entradas de blog estáticas, pero fallan en páginas renderizadas con JavaScript, docs protegidas por Cloudflare y sitios que devuelven 403 a clientes genéricos. CrawlForge maneja los tres casos con extract_content (legibilidad), scrape_with_actions (ejecución de JS) y stealth_mode (anti-bot).

¿Cuánto cuesta indexar 100 páginas con CrawlForge + LlamaIndex?+

Las páginas estáticas con extract_content cuestan 2 credits cada una, así que 100 páginas = 200 credits. Las páginas protegidas por Cloudflare o con mucho JS cuestan 5 credits cada una (500 credits para 100). Ambas caben dentro del plan gratuito de 1.000 credits para una construcción puntual del índice.

¿Puede CrawlForge actuar como herramienta de un agente de LlamaIndex?+

Sí. Envuelve cualquier llamada a la API de CrawlForge en un FunctionTool de LlamaIndex y regístralo con un ReActAgent u OpenAIAgent. El agente decide cuándo hacer scraping de una URL o ejecutar una búsqueda web según la consulta del usuario. Consulta la sección de agentes arriba para ver código funcional.

¿Es compatible CrawlForge con transformaciones de consulta de LlamaIndex como HyDE?+

CrawlForge es una fuente de datos, no una capa de recuperación. Las transformaciones de consulta ocurren dentro de LlamaIndex tras la ingesta. CrawlForge devuelve markdown limpio o datos estructurados que alimentan VectorStoreIndex; todo lo posterior (HyDE, razonamiento multipaso, SubQuestionQueryEngine) funciona sin cambios.

¿Cómo mantengo actualizado un índice de LlamaIndex con datos web en vivo?+

Programa un cron diario que vuelva a ejecutar tu CrawlForgeReader sobre la misma lista de URLs y reconstruya el índice con VectorStoreIndex.from_documents. Como CrawlForge devuelve markdown limpio, los documentos tienen siempre la misma forma, así que los embeddings son estables. Para actualizaciones incrementales, usa las APIs de upsert de LlamaIndex con un ID de documento derivado de la URL.

Artículos relacionados

Cómo hacer scraping de sitios web con Claude Code (guía 2026)
Tutorials

Cómo hacer scraping de sitios web con Claude Code (guía 2026)

Haz scraping de cualquier sitio web desde tu terminal con Claude Code y CrawlForge MCP. Obtén páginas, extrae datos y esquiva el anti-bot, en menos de 2 minutos.

C
CrawlForge Team
|
14 abr
|
10m
Cómo hacer scraping de sitios web en Cursor IDE con CrawlForge MCP
Tutorials

Cómo hacer scraping de sitios web en Cursor IDE con CrawlForge MCP

Convierte Cursor IDE en una estación de trabajo de web scraping. Conecta CrawlForge MCP y extrae datos estructurados de cualquier sitio sin salir de tu editor.

C
CrawlForge Team
|
14 abr
|
9m
Cómo hacer scraping de sitios web en Zed AI con CrawlForge MCP
Tutorials

Cómo hacer scraping de sitios web en Zed AI con CrawlForge MCP

Añade web scraping a Zed AI en 3 minutos. Configura CrawlForge MCP en Zed para que tu editor pueda obtener, extraer e investigar datos web en vivo bajo demanda.

C
CrawlForge Team
|
14 abr
|
9m

Pie de página

CrawlForge

Web scraping empresarial para agentes de IA. 27 herramientas MCP especializadas diseñadas para desarrolladores modernos que crean sistemas inteligentes.

Producto

  • Funciones
  • Playground
  • Precios
  • Casos de uso
  • Integraciones
  • Alternativas
  • Registro de cambios

Recursos

  • Primeros pasos
  • Referencia de la API
  • Plantillas
  • Guías
  • Blog
  • Glosario
  • Preguntas frecuentes
  • Mapa del sitio

Desarrolladores

  • Protocolo MCP
  • Claude Desktop
  • Cursor IDE
  • LangChain
  • LlamaIndex

Empresa

  • Acerca de
  • Contacto
  • Privacidad
  • Términos
  • Uso aceptable
  • Cookies

Mantente al día

Recibe las últimas novedades sobre nuevas herramientas y funciones.

Creado con Next.js y el protocolo MCP

© 2025-2026 CrawlForge. Todos los derechos reservados.