Los sitios de comercio electrónico protegen las páginas de productos con CAPTCHA para evitar la manipulación automática de precios. CaptchaAI le permite crear sistemas confiables de seguimiento de precios que manejan estos desafíos automáticamente.
El problema
Los robots de seguimiento de precios se enfrentan a CAPTCHA en las principales plataformas:
| Plataforma | Tipo CAPTCHA | gatillo |
|---|---|---|
| Amazonas | Imagen CAPTCHA, reCAPTCHA | Alto volumen de solicitudes |
| Walmart | Cloudflare Turnstile | Detección de robots |
| eBay | reCAPTCHA v2 | Patrones sospechosos |
| Mejor compra | Cloudflare Challenge | Todo el tráfico automatizado |
| Tiendas Shopify | reCAPTCHA v3 | Varía según la configuración de la tienda. |
Sin el manejo de CAPTCHA, su canal de monitoreo falla silenciosamente, dejando brechas de precios en sus datos.
Arquitectura
Scheduler (every 30 min)
→ URL Queue
→ Scraper Workers (5-10 concurrent)
→ Fetch page
→ CAPTCHA detected?
→ Yes → CaptchaAI → Solve → Retry page
→ No → Parse prices
→ Store in database
→ Alert on price changes
Implementación
Monitor de precios (Python)
import requests
import time
import re
import json
import os
from datetime import datetime
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
BASE_URL = "https://ocr.captchaai.com"
def solve_captcha(method, params):
params["key"] = API_KEY
params["method"] = method
resp = requests.get(f"{BASE_URL}/in.php", params=params)
if not resp.text.startswith("OK|"):
raise Exception(f"Submit failed: {resp.text}")
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{BASE_URL}/res.php", params={
"key": API_KEY, "action": "get", "id": task_id,
})
if result.text == "CAPCHA_NOT_READY":
continue
if result.text.startswith("OK|"):
return result.text.split("|", 1)[1]
raise Exception(f"Solve failed: {result.text}")
raise TimeoutError("CAPTCHA solve timed out")
def fetch_with_captcha(url, session):
"""Fetch a page, solving CAPTCHAs if encountered."""
resp = session.get(url)
# Check for reCAPTCHA
match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', resp.text)
if match:
site_key = match.group(1)
token = solve_captcha("userrecaptcha", {
"googlekey": site_key,
"pageurl": url,
})
resp = session.post(url, data={"g-recaptcha-response": token})
# Check for Turnstile
match = re.search(
r'class="cf-turnstile"[^>]*data-sitekey=["\']([^"\']+)', resp.text
)
if match:
site_key = match.group(1)
token = solve_captcha("turnstile", {
"sitekey": site_key,
"pageurl": url,
})
resp = session.post(url, data={"cf-turnstile-response": token})
return resp
def extract_price(html, selectors):
"""Extract price from HTML using regex patterns."""
for pattern in selectors:
match = re.search(pattern, html)
if match:
price_str = match.group(1).replace(",", "")
return float(price_str)
return None
def monitor_prices(products):
"""Monitor prices for a list of products."""
session = requests.Session()
session.headers["User-Agent"] = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/120.0.0.0"
)
results = []
for product in products:
try:
resp = fetch_with_captcha(product["url"], session)
price = extract_price(resp.text, product["selectors"])
results.append({
"name": product["name"],
"url": product["url"],
"price": price,
"timestamp": datetime.utcnow().isoformat(),
"status": "ok",
})
print(f" {product['name']}: ${price}")
except Exception as e:
results.append({
"name": product["name"],
"url": product["url"],
"price": None,
"timestamp": datetime.utcnow().isoformat(),
"status": f"error: {e}",
})
print(f" {product['name']}: ERROR - {e}")
return results
# Define products to monitor
products = [
{
"name": "Wireless Headphones",
"url": "https://example.com/product/headphones",
"selectors": [
r'class="price"[^>]*>\$?([\d,]+\.?\d*)',
r'itemprop="price" content="([\d.]+)"',
],
},
{
"name": "Bluetooth Speaker",
"url": "https://example.com/product/speaker",
"selectors": [
r'class="price"[^>]*>\$?([\d,]+\.?\d*)',
],
},
]
print("Starting price check...")
results = monitor_prices(products)
# Save results
with open("prices.json", "w") as f:
json.dump(results, f, indent=2)
Implementación de Node.js
const axios = require("axios");
const cheerio = require("cheerio");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
async function solveCaptcha(method, params) {
params.key = API_KEY;
params.method = method;
const submit = await axios.get("https://ocr.captchaai.com/in.php", {
params,
});
const taskId = String(submit.data).split("|")[1];
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: taskId },
});
const text = String(poll.data);
if (text === "CAPCHA_NOT_READY") continue;
if (text.startsWith("OK|")) return text.split("|").slice(1).join("|");
throw new Error(text);
}
throw new Error("Timeout");
}
async function monitorPrice(url) {
const resp = await axios.get(url);
const $ = cheerio.load(resp.data);
// Check for reCAPTCHA
const siteKey = $(".g-recaptcha").attr("data-sitekey");
if (siteKey) {
const token = await solveCaptcha("userrecaptcha", {
googlekey: siteKey,
pageurl: url,
});
// Re-fetch with token
const formResp = await axios.post(url, { "g-recaptcha-response": token });
return cheerio.load(formResp.data);
}
const price = $('[itemprop="price"]').attr("content") || $(".price").text();
return parseFloat(price.replace(/[^0-9.]/g, ""));
}
Programación
Ejecute comprobaciones cada 30 minutos con cron:
# crontab -e
*/30 * * * * cd /opt/monitor && python price_monitor.py >> /var/log/prices.log 2>&1
O utilice la biblioteca schedule de Python:
import schedule
schedule.every(30).minutes.do(lambda: monitor_prices(products))
while True:
schedule.run_pending()
time.sleep(60)
Estimación de costos
| Volumen | CAPTCHAs/Day | Est. Costo diario |
|---|---|---|
| 50 productos, cada 30 min. | ~2,400 | ~$2-5 |
| 200 productos, cada 15 min. | ~19,200 | ~$15-30 |
| 1000 productos, por hora | ~24.000 | ~$20-40 |
No todas las cargas de páginas activan CAPTCHA. Los costos reales pueden ser entre un 50% y un 70% más bajos.
Preguntas frecuentes
¿Cómo detecto cambios de precios?
Compare los precios actuales con los valores almacenados. Las alertas sobre cambios >5% ayudan a filtrar el ruido de fluctuaciones menores.
¿Me bloquearán incluso si resuelvo CAPTCHA?
Gire los proxies y los agentes de usuario para minimizar el bloqueo. Solicitudes de espacio a lo largo del tiempo en lugar de búsquedas en ráfagas.
¿Puedo monitorear los precios en múltiples monedas?
Sí. Analice el símbolo de moneda junto con el precio. CaptchaAI funciona globalmente independientemente de la ubicación del sitio de destino.
Guías relacionadas
- Manejar CAPTCHA en Web Scraping
- Raspar sin bloquearse
- Recopilación de datos de investigación de mercado