Volver al blog

Ollama Web Scraping: Ejecuta un scraper LLM local sin clave de API.

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

23-Jul-2026

TL;DR:

  • Ollama ejecuta el modelo de extracción en tu propia máquina, por lo que el paso de LLM de un scraper no requiere una clave API ni un costo por token.
  • Lo que Ollama no hace es obtener. Un modelo local no tiene navegador ni acceso a la red en una página; estructura el texto que le entregas.
  • La diferencia se muestra en un script. Una simple solicitud GET a una página de demostración renderizada con JavaScript te da 0 bloques de citas; la misma URL a través de la API Universal de Scraping de Scrapeless con js_render te da los 10 — y ese HTML renderizado es lo que el modelo lee.
  • La extracción es real en esta guía. Una ejecución en vivo alimentó tres bloques de citas renderizadas a un modelo local qwen2.5:0.5b y devolvió JSON limpio con el texto y el autor de cada uno — sin llamadas a la nube en ninguna parte.
  • Los modelos pequeños quieren menos ruido. Recorta el HTML a la región del contenido antes de que el modelo lo vea; un modelo de 0.5B en un snippet enfocado es rápido y preciso, donde la página completa no encajaría.
  • Gratis para empezar por el lado de la obtención. Crea tu clave API de Scrapeless en app.scrapeless.com.

Por qué ejecutar el modelo del scraper localmente

Un scraper LLM convierte el contenido de la página en registros estructurados, y ese modelo no tiene que vivir en la nube de otra persona. Ollama ejecuta modelos abiertos en tu propio hardware detrás de una pequeña API HTTP, por lo que el paso de extracción no tiene clave API, ni límite de tasa, ni costo por token — útil cuando procesas muchas páginas o manejas datos que preferirías no enviar a un tercero.

Lo que un modelo local no puede hacer es obtener. No tiene navegador, no mantiene sesiones, y en una página renderizada por JavaScript, una simple solicitud HTTP devuelve un markup sin contenido. Así que un scraper web de Ollama es de dos capas: una capa de obtención que devuelve HTML renderizado fiel, y el modelo local como la capa de extracción que lo convierte en registros. Esta guía utiliza la API Universal de Scraping de Scrapeless para la primera capa. Si en su lugar quieres dar a un modelo local búsqueda web en vivo — el modelo llama a una herramienta de búsqueda y razona sobre los resultados — ese es otro trabajo, cubierto por la guía de búsqueda web local de LLM; esta publicación trata sobre extraer datos estructurados de una página específica.

Requisitos previos

  • Ollama instalado y ejecutándose, con un modelo pequeño y amigable para herramientas descargado: ollama pull qwen2.5:0.5b.
  • Python 3.9 o posterior con requests.
  • Una clave API de Scrapeless desde el panel, exportada como SCRAPELESS_API_KEY.

Instalación

Descarga un modelo pequeño e instala la única dependencia de Python. El servidor de Ollama escucha en localhost:11434 una vez que se está ejecutando.

bash Copy
ollama pull qwen2.5:0.5b
pip install requests

Mantén tu clave en el entorno, nunca en el código fuente:

bash Copy
export SCRAPELESS_API_KEY="sk_tu_clave_de_scrapeless"

Obtener una página que el modelo realmente pueda leer

La calidad de extracción está limitada por la fidelidad de obtención, así que comienza por ahí. En una página renderizada por JavaScript, el documento que recibe un cliente HTTP simple no es el documento que ve un lector — el contenido solo llega después de que los scripts construyen el DOM, un ciclo de vida definido por la especificación de scripting de HTML. Un script cuenta la diferencia:

python Copy
# fetch_rendered.py — GET simple vs renderizado del lado del servidor, misma URL
import os

import requests

URL = "https://quotes.toscrape.com/js/"
MARKER = '<div class="quote">'

plain = requests.get(URL, timeout=60).text
print("caracteres GET simples:", len(plain), "| bloques de citas:", plain.count(MARKER))

resp = requests.post(
    "https://api.scrapeless.com/api/v2/unlocker/request",
    headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
    json={"actor": "unlocker.webunlocker", "input": {"url": URL, "js_render": True}},
    timeout=120,
)
resp.raise_for_status()
rendered = resp.json().get("data", "")
print("caracteres renderizados:", len(rendered), "| bloques de citas:", rendered.count(MARKER))

La ejecución imprime 0 bloques de citas para la obtención simple y 10 para la renderizada:

text Copy
caracteres GET simples: 5806 | bloques de citas: 0
caracteres renderizados: 8940 | bloques de citas: 10

La renderización, desbloqueo y enrutamiento por proxy ocurren del lado del servidor en esa única solicitud POST — la API Universal de Scraping es la capa de obtención, y el HTML renderizado es lo que el modelo local extrae.

Extraer con un modelo local

Ahora entrega el contenido a Ollama. Dos cosas mantienen un modelo pequeño preciso: recorta el HTML a la región del contenido para que el modelo no esté leyendo el chrome de la página, y pide JSON con format: "json" para que la salida sea procesable. El endpoint /api/generate de Ollama toma el nombre del modelo y la solicitud y devuelve la finalización, documentada en la referencia de la API de Ollama:

python Copy
# extract_local.py — obtener, recortar y extraer con un modelo local de Ollama
import json
import os
import re

import requests

resp = requests.post(
    "https://api.scrapeless.com/api/v2/unlocker/request",
    headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
    json={"actor": "unlocker.webunlocker", "input": {"url": "https://quotes.toscrape.com/js/", "js_render": True}},
    timeout=120,
)
resp.raise_for_status()
html = resp.json().get("data", "")

# Recorta a los primeros tres bloques de citas — un modelo local pequeño funciona mejor con menos ruido.
blocks = re.findall(r'<div class="quote">.*?</small>', html, re.S)[:3]
snippet = "\n".join(blocks)

completion = requests.post(
    "http://localhost:11434/api/generate",
    json={
        "model": "qwen2.5:0.5b",
        "prompt": 'Extrae cada cita de este HTML en JSON con la forma exacta '
                  '{"quotes":[{"text":"...","author":"..."}]}. Responde SOLAMENTE con el JSON.\n\nHTML:\n' + snippet,
        "stream": False,
        "format": "json",
        "options": {"temperature": 0, "num_predict": 400},
    },
    timeout=600,
)
data = json.loads(completion.json()["response"])

records = data["quotes"]
print("registros:", len(records))
print("primer autor:", records[0]["author"])
print("primer texto:", records[0]["text"])

La ejecución local devolvió tres registros, con el texto y el autor intactos en el primero:

text Copy
registros: 3
primer autor: Albert Einstein
primer texto: El mundo tal como lo hemos creado es un proceso de nuestro pensamiento. No se puede cambiar sin cambiar nuestro pensamiento.

Ese es todo el raspador, y la mitad del modelo nunca tocó la red: una POST a Scrapeless para obtener y renderizar, una llamada a localhost para extraer. Escala el número de bloques por llamada a lo que tu hardware maneje: un modelo de 0.5B en CPU es más lento que un endpoint en la nube, así que agrupa en pequeños lotes y mantén la entrada ajustada.

Obtén tu clave API en el plan gratuito: app.scrapeless.com

Patrones avanzados

  • Ajusta el modelo al hardware. qwen2.5:0.5b es lo suficientemente rápido para demostrar en CPU; un modelo de 3B o 7B extrae más de manera confiable de páginas más desordenadas si tienes la memoria y la paciencia. La forma de la solicitud no cambia: solo cambia la cadena model.
  • Recorta antes de pedir. Aislar el contenedor de contenido es la única mayor palanca de calidad para un modelo pequeño. Envía el bloque repetido, no todo el documento, y el costo de tokens y la tasa de error disminuyen.
  • Mantén format: "json" y temperature: 0. El modo JSON restringe la salida a JSON procesable, y temperatura cero mantiene la extracción estable a través de ejecuciones; ninguno es opcional para un raspador.
  • Haz un bucle en Python, no en la solicitud. Una región de contenido por solicitud mantiene los registros separados y hace que una mala extracción sea atribuible a una página específica.

Resolución de problemas

  • Conexión rechazada en localhost:11434. El servidor de Ollama no está funcionando. Inícialo (ollama serve) y confirma que el modelo está disponible con ollama list.
  • Cero bloques para extraer. Tu obtención devolvió el HTML pre-renderizado. Cuenta un elemento conocido de la manera en que lo hace el primer script; una obtención casi vacía es un problema de renderizado, solucionado con js_render, no un problema del modelo.
  • El modelo retorna prosa, no JSON. Has omitido format: "json". Con ello, Ollama restringe la salida; sin él, estás procesando buena voluntad.
  • La extracción es lenta o se pierden registros. El modelo es demasiado pequeño para el tamaño de la entrada. Recorta a menos bloques por llamada, o cambia a un modelo más grande: los modelos locales pequeños sacrifican precisión por velocidad, y un aviso más corto y limpio es la forma en que recuperas ambas.

Conclusión

Ollama se gana su lugar como la capa de extracción que funciona donde tú lo haces: modelos abiertos en tu propio hardware, sin clave y sin factura por token, convirtiendo el contenido de la página en JSON. La capa que decide si algo de eso es posible es la obtención: el conteo de 0 frente a 10 del primer script lo resuelve, y un POST renderizado en el servidor cierra la brecha. Conecta los dos y una página renderizada se convierte en registros estructurados, con la mitad del modelo permaneciendo completamente en localhost.
Crea una cuenta gratuita de Scrapeless para obtener una clave API, y la documentación para desarrolladores cubre los parámetros unlocker.webunlocker. Consulta los precios de Scrapeless cuando planees un trabajo recurrente.

FAQ

P: ¿Puede Ollama extraer datos de sitios web por sí mismo?

No. Ollama ejecuta un modelo de lenguaje localmente; no tiene un cliente HTTP para páginas arbitrarias y no renderiza JavaScript. Estructura el texto que le proporcionas. Combínalo con una capa de obtención — aquí la API Universal de Scraping de Scrapeless, que renderiza la página del lado del servidor — y el modelo local maneja la extracción.

P: ¿En qué se diferencia esto de dar a un LLM local una búsqueda web?

Dirección. Una configuración de búsqueda web permite al modelo llamar a una herramienta de búsqueda y razonar sobre los resultados para responder una pregunta; esta configuración obtiene una página específica que elijas y hace que el modelo extraiga campos estructurados de ella. Una es respuesta aumentada por búsqueda, la otra es un pipeline de scraping; la guía de búsqueda web con LLM local mencionada arriba cubre la primera.

P: ¿Qué modelo local debo usar para la extracción?

El más pequeño que contenga tu esquema. La extracción con un aviso JSON estricto y temperatura: 0 no requiere mucho razonamiento, por lo que un modelo de 0.5B funciona en un fragmento reducido, como muestra la ejecución anterior. Pasa a un modelo de 3B o más grande solo cuando las páginas son lo suficientemente desordenadas como para que el pequeño pierda campos.

P: ¿Necesito una GPU?

No. La ejecución en esta guía utilizó un modelo de 0.5B en CPU. Una GPU hace que los modelos más grandes sean prácticos y todo más rápido, pero un modelo pequeño en CPU es suficiente para construir y probar el pipeline.

P: ¿Es legal realizar scraping con un modelo local?

Ejecutar el modelo localmente no cambia las reglas de recopilación. Obtén solo páginas públicas, respeta los términos del sitio y las directivas de robots estandarizadas por el Protocolo de Exclusión de Robots, mantén los volúmenes limitados y maneja cualquier dato personal de acuerdo a las leyes que te apliquen.

En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.

Artículos más populares

Catalogar