`fetch_markdown()` a continuación es el límite del SDK. Devuelve texto a un analizador; no afirma que la API ya ha identificado el precio del producto.
### Paso 3: Extraer y Normalizar Precios
El analizador coincide con un marcador explícito y la moneda esperada. Para un sitio objetivo real, prefiera un selector HTML específico del sitio o un campo de datos estructurados documentado, respaldado por ejemplos de precios de venta, productos no disponibles y múltiples variantes. Nunca tome el primer número parecido a una moneda en una página y lo llame "el precio".
### Paso 4: Almacenar Historial de Precios en SQLite
Almacene tanto las observaciones válidas como las rechazadas. SQLite es apropiado para un tutorial de proceso único y cargas de trabajo modestas; un monitor más grande puede necesitar una base de datos de servidor transaccional y una cola de trabajo. La tabla incluye `product_id`, `observed_price`, `currency`, `observed_at`, `source_url` y `extraction_status`.
### Paso 5: Detectar Cambios de Precio Significativos
Para el precio antiguo `P₀` y el nuevo precio `P₁`, el cambio absoluto es `P₁ − P₀`; el cambio porcentual es `(P₁ − P₀) / P₀ × 100`. No calcule un cambio porcentual cuando la línea base sea cero. Compare solo valores con la misma moneda y variante de producto. Las alertas de ejemplo se activan con un cambio absoluto de al menos 5 unidades de moneda **y** un cambio relativo de al menos 3%; ajuste ambos umbrales para su negocio.
### Paso 6: Programar Verificaciones y Generar Alertas
Ejecute el script desde cron, un programador de trabajadores o su sistema de orquestación. Este ejemplo imprime una alerta que un servicio circundante puede entregar. La programación y la notificación no son características de la API de Crawl. Registre los errores de rastreo por separado y vuelva a intentar las fallas transitorias con un retroceso limitado.
```python
import os
import re
import sqlite3
from datetime import datetime, timezone
from decimal import Decimal, InvalidOperation
from nstdata_ai_crawl import Format, NstDataClient, ScrapeRequestDto
DB_PATH = "prices.sqlite3"
PRODUCTS = [
{
"product_id": "widget-standard",
"product_name": "Widget Standard",
"source_url": "https://shop.example.com/products/widget",
"currency": "USD",
}
]
def fetch_markdown(client: NstDataClient, url: str) -> str:
result = client.submit_scrape_task_sync(
ScrapeRequestDto(
url=url,
formats=[Format.MARKDOWN],
onlyMainContent=True,
timeout=60000,
)
)
body = result.data.get_markdown()
if not body or not body.strip():
raise ValueError("No usable product page content")
return body
def parse_price(markdown: str, currency: str) -> Decimal:
# Reemplace este marcador específico del sitio con un analizador probado para su sitio.
pattern = rf"(?m)^Price:\s*{re.escape(currency)}\s+([0-9]+(?:\.[0-9]{{2}})?)\s*$"
matches = re.findall(pattern, markdown)
if len(matches) != 1:
raise ValueError(f"Expected one {currency} price marker, found {len(matches)}")
try:
amount = Decimal(matches[0])
except InvalidOperation as exc:
raise ValueError("Invalid decimal price") from exc
if amount <= 0:
raise ValueError("Price must be positive")
return amount
def init_db(db: sqlite3.Connection) -> None:
db.execute("""
CREATE TABLE IF NOT EXISTS observations (
id INTEGER PRIMARY KEY,
product_id TEXT NOT NULL,
observed_price TEXT,
currency TEXT NOT NULL,
observed_at TEXT NOT NULL,
source_url TEXT NOT NULL,
extraction_status TEXT NOT NULL
)
""")
db.commit()
def previous_price(db: sqlite3.Connection, product_id: str, currency: str):
row = db.execute(
"""SELECT observed_price FROM observations
WHERE product_id = ? AND currency = ? AND extraction_status = 'ok'
ORDER BY id DESC LIMIT 1""",
(product_id, currency),
).fetchone()
return Decimal(row[0]) if row else None
def save(db, product, observed_at, status, price=None):
db.execute(
"""INSERT INTO observations
(product_id, observed_price, currency, observed_at, source_url, extraction_status)
VALUES (?, ?, ?, ?, ?, ?)""",
(
product["product_id"],
str(price) if price is not None else None,
product["currency"],
observed_at,
product["source_url"],
status,
),
)
db.commit()
def main() -> None:
with sqlite3.connect(DB_PATH) as db:
init_db(db)
with NstDataClient(os.environ["NSTDATA_API_TOKEN"]) as client:
for product in PRODUCTS:
observed_at = datetime.now(timezone.utc).isoformat()
try:
markdown = fetch_markdown(client, product["source_url"])
price = parse_price(markdown, product["currency"])
baseline = previous_price(
db, product["product_id"], product["currency"]
)
Para una comprobación de parser local antes de cualquier llamada de red, `parse_price("Price: USD 129.00", "USD")` debería devolver `Decimal("129.00")`. Debería rechazar `"List price: USD 129.00"` y una página con dos marcadores `Price:`. Un parser de producción necesita accesorios adicionales para descuentos, símbolos de moneda, separadores específicos de la localidad y texto de fuera de stock. Una entrada de `crontab` como `0 */6 * * * /path/to/python /path/to/price_watch.py >> /path/to/price_watch.log 2>&1` se ejecuta cada seis horas; ajusta la frecuencia para adaptarse a tus derechos, presupuesto y necesidades de frescura.
## ¿Por qué usar Nstdata Crawl para el monitoreo de precios?
Nstdata es útil como la capa de recolección cuando las páginas de productos públicas aprobadas necesitan renderización, recuperación repetida y salida consistente. Su API de una sola página documentada, salida en Markdown y HTML, capturas de pantalla, tareas sincrónicas y asincrónicas, y opciones de ubicación de proxy pueden reducir el código de acceso a la página que mantienes. Esas capacidades no extraen un precio de manera confiable en cada tienda. El parser, la base de datos, el programador y la entrega de alertas siguen siendo tu responsabilidad. La [guía de recolección de datos automatizada](https://www.nstdata.io/blog/automated-data-collection) de Nstdata proporciona un contexto operativo relacionado.
<a style="margin: 8px; display: inline-block; text-decoration: none; border-left-width: 0px;" href="https://app.nstdata.io/auth/register?utm_source=official&utm_medium=blog&utm_campaign=/building-a-price-watching-agent-with-crawl-api/">
<div style="font-weight:bold; max-width:400px; padding:12px 40px; background:#646AEE; border-radius:5px; border:2px solid #646AEE; color:#fff; font-size:18px;">
Prueba Nstdata Gratis →
</div>
</a>
### Ventajas Clave de Nstdata Crawl
La separación te permite cambiar un parser de página sin cambiar tu cliente de recolección. Markdown es conveniente cuando el precio es visible como texto; HTML es preferible cuando necesitas un dato estructurado exacto o un campo DOM. Una captura de pantalla puede ayudar a diagnosticar desajustes visuales. La configuración de la región del proxy puede ser importante cuando la moneda o la oferta mostrada varía por ubicación, pero la variación geográfica debe ser capturada como parte de la clave de observación en lugar de ser tratada como un cambio de precio.
### Ejemplo de Integración del SDK de Python
`fetch_markdown()` arriba es el pequeño adaptador del SDK. Para un nuevo comerciante, primero recoge un puñado de páginas de muestra permitidas y escribe pruebas de extracción específicas del sitio. Solo entonces activa las verificaciones programadas. Evita promover una métrica de “página recuperada” a una métrica de “precio observado con éxito”.
## Pruebas, Costos y Problemas Comunes
Rastrea el costo de solicitud de Crawl, el tráfico de proxy facturado por separado donde se utilice, el costo de la base de datos y del programador, y los tokens del modelo si un LLM escribe resúmenes. El denominador útil es **observaciones de precio válidas y correctamente emparejadas**, no solicitudes en bruto. Si los reintentos aumentan o la extracción falla después de un cambio de diseño, el costo por observación válida se eleva incluso si el precio por unidad de solicitud se mantiene fijo.
### Errores Comunes y Solución de Problemas
Para contenido en blanco, inspecciona el estado renderizado de la página y el selector esperado. Para 403/429, reduce la tasa y revisa la política de acceso en lugar de volver a intentar agresivamente. Para un aumento de precio improbable, inspecciona la promoción, variante, tamaño del paquete, moneda y cambios en el parser. Utiliza una clave de observación o alerta única si un programador puede ejecutarse dos veces, y asegúrate de que una fila de error nunca sobrescriba la última base válida.
### Cómo Medir la Calidad del Monitoreo
Etiqueta una muestra de páginas objetivo a mano. **La precisión de extracción** es parses de precio correctos / páginas parseadas. **La tasa de recolección válida** es observaciones aceptadas / páginas intentadas. **La precisión de detección de cambios** es cambios verdaderos / alertas revisadas. **Frescura** es el tiempo desde el cambio de página hasta la observación registrada; mídelo con accesorios controlados o eventos de actualización conocidos. **La tasa de alerta duplicada** son alertas repetidas para el mismo cambio observado / todas las alertas. Revisa estos por comerciante y plantilla de página porque un promedio global puede ocultar un parser roto.
<a style="margin: 8px; display: inline-block; text-decoration: none; border-left-width: 0px;" href="https://app.nstdata.io/auth/register?utm_source=official&utm_medium=blog&utm_campaign=/building-a-price-watching-agent-with-crawl-api/">
<div style="font-weight:bold; max-width:400px; padding:12px 40px; background:#646AEE; border-radius:5px; border:2px solid #646AEE; color:#fff; font-size:18px;">
Prueba Nstdata Gratis →
</div>
</a>
## FAQ
### ¿Cómo construyo un agente de monitoreo de precios?
Lee las páginas de productos permitidas, extrae un precio claramente definido, almacena observaciones con sello de tiempo, compara con el último registro coincidente válido y alerta solo después de la validación.
### ¿Puede un API de Raspado extraer precios automáticamente?
Un API de Raspado recupera el contenido de la página. Aún necesitas un parser específico del sitio o una capa de extracción para identificar el precio correcto y la variante del producto.
### ¿Con qué frecuencia se deben verificar los precios?
Elige un horario basado en los requisitos de frescura del negocio, la política del sitio, la frecuencia de cambios y el costo. Mide si ese intervalo detecta cambios a tiempo.
### ¿Cómo se deben almacenar los precios históricos de los productos?
Utiliza un ID de producto estable, un monto decimal, moneda, URL de origen, tiempo de observación, estado de extracción y cualquier clave de variante o región necesaria para comparar como con como.