Perché automatizzati di monitoraggio dei prezzi
Nei mercati e-commerce competitivi, i prezzi cambiano costantemente. Un concorrente potrebbe cadere il loro prezzo del 5% alle 2 AM, e al momento si nota, hai già perso una giornata di vendite. Il monitoraggio automatizzato dei prezzi elimina questo punto cieco monitorando continuamente i prezzi dei concorrenti e avvisando i cambiamenti in tempo reale.
Che tu sia un rivenditore che regola i prezzi per rimanere competitivo, un marchio di monitoraggio MAP (Minimum Advertised Price) conformità, o un analista che traccia le tendenze del mercato, un sistema di monitoraggio dei prezzi ben costruito paga per sé rapidamente. L'ingrediente chiave che lo rende tutto funziona in modo affidabile è una robusta infrastruttura proxy — senza di essa, le vostre richieste di monitoraggio vengono bloccate entro ore. Per uno sguardo più ampio alla raccolta di dati e-commerce, vedere il nostro e-commerce dati scraping guida.
Architettura di un sistema di monitoraggio dei prezzi
Un sistema di monitoraggio dei prezzi di produzione ha quattro componenti principali: un gestore di URL, un motore di demolizione, un data store e uno strato di allerta.
| Componenti | Responsabilità | Tecnologie |
|---|---|---|
| Gestione dell'URL | Memorizza gli URL di destinazione, la pianificazione dei metadati e la frequenza di scraping | PostgreSQL, Redis |
| Motore di scorrimento | Fetches pagine attraverso i proxy, estrae i prezzi | Python/Node.js, ProxyHat, BeautifulSoup/Cheerio |
| Data Store | Negozi cronologia dei prezzi con timestamp | PostgreSQL, TimescaleDB, ClickHouse |
| Sistema di allarme | Rileva le modifiche, invia le notifiche | Webhooks, Slack, Email, SMS |
Strategia di programmazione
Non tutti i prodotti hanno bisogno della stessa frequenza di monitoraggio. Gli articoli ad alta priorità (tutti i migliori 100 SKU, i prodotti diretti concorrenti) potrebbero avere bisogno di controlli orari, mentre gli articoli a coda lunga possono essere controllati ogni giorno. Prioritare basato su:
- volatilità dei prezzi: I prodotti che cambiano i prezzi hanno spesso bisogno di controlli più frequenti.
- Impatto delle entrate: I vostri bestseller meritano una maggiore priorità di monitoraggio.
- Densità competitiva: Categorie con molti concorrenti hanno bisogno di un monitoraggio più stretto.
Impostazione della rotazione del proxy per il monitoraggio
Il monitoraggio dei prezzi significa colpire ripetutamente gli stessi URL nei giorni, settimane e mesi. Questo modello è esattamente ciò che i sistemi anti-bot sono progettati per rilevare. I proxy residenziali con rotazione automatica sono essenziali.
Configurazione ProxyHat
# Standard rotating proxy (new IP per request)
http://USERNAME:PASSWORD@gate.proxyhat.com:8080
# Geo-targeted for regional pricing (e.g., US prices)
http://USERNAME-country-US:PASSWORD@gate.proxyhat.com:8080
# Session-based for multi-page price checks
http://USERNAME-session-price001:PASSWORD@gate.proxyhat.com:8080Per il monitoraggio dei prezzi, la rotazione per richiesta funziona meglio perché ogni controllo dei prezzi è un'operazione indipendente. Uso Prossi geo-targeti quando si controllano le differenze regionali dei prezzi.
Attuazione di Python
Ecco un sistema completo di monitoraggio dei prezzi costruito con Python, utilizzando ProxyHat Python SDK.
Modulo del grattacielo di prezzo
import requests
from bs4 import BeautifulSoup
import json
import time
import random
from datetime import datetime
from dataclasses import dataclass, asdict
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
]
@dataclass
class PriceResult:
url: str
price: float | None
currency: str | None
in_stock: bool
scraped_at: str
seller: str | None = None
def scrape_price(url: str, selectors: dict) -> PriceResult:
"""Scrape a product price from any e-commerce site."""
headers = {
"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
}
proxies = {"http": PROXY_URL, "https": PROXY_URL}
try:
response = requests.get(url, headers=headers, proxies=proxies, timeout=30)
response.raise_for_status()
except requests.RequestException as e:
return PriceResult(
url=url, price=None, currency=None,
in_stock=False, scraped_at=datetime.utcnow().isoformat()
)
soup = BeautifulSoup(response.text, "html.parser")
price = extract_price(soup, selectors.get("price"))
currency = selectors.get("currency", "USD")
in_stock = check_stock(soup, selectors.get("stock"))
return PriceResult(
url=url,
price=price,
currency=currency,
in_stock=in_stock,
scraped_at=datetime.utcnow().isoformat(),
)
def extract_price(soup, selector: str) -> float | None:
"""Extract and parse price from a CSS selector."""
if not selector:
return None
el = soup.select_one(selector)
if not el:
return None
text = el.get_text(strip=True)
# Remove currency symbols, commas, spaces
cleaned = "".join(c for c in text if c.isdigit() or c == ".")
try:
return float(cleaned)
except ValueError:
return None
def check_stock(soup, selector: str) -> bool:
"""Check if product is in stock."""
if not selector:
return True
el = soup.select_one(selector)
if not el:
return False
text = el.get_text(strip=True).lower()
return "in stock" in text or "available" in text
# Site-specific selector configurations
SITE_SELECTORS = {
"amazon.com": {
"price": "span.a-price-whole",
"stock": "#availability span",
"currency": "USD",
},
"walmart.com": {
"price": "[data-testid='price-wrap'] span.f2",
"stock": "[data-testid='fulfillment-badge']",
"currency": "USD",
},
"target.com": {
"price": "[data-test='product-price']",
"stock": "[data-test='fulfillmentSection']",
"currency": "USD",
},
}Programma di monitoraggio
import schedule
import threading
from collections import defaultdict
class PriceMonitor:
def __init__(self, db_connection):
self.db = db_connection
self.price_history = defaultdict(list)
def add_product(self, url: str, site: str, check_interval_minutes: int = 60):
"""Register a product for monitoring."""
selectors = SITE_SELECTORS.get(site, {})
def check():
result = scrape_price(url, selectors)
self.price_history[url].append(result)
self.store_result(result)
self.check_alerts(url, result)
time.sleep(random.uniform(1, 3))
schedule.every(check_interval_minutes).minutes.do(check)
def store_result(self, result: PriceResult):
"""Store price result in database."""
# Insert into price_history table
self.db.execute(
"INSERT INTO price_history (url, price, currency, in_stock, scraped_at) "
"VALUES (%s, %s, %s, %s, %s)",
(result.url, result.price, result.currency,
result.in_stock, result.scraped_at)
)
def check_alerts(self, url: str, result: PriceResult):
"""Check if price change triggers an alert."""
history = self.price_history[url]
if len(history) < 2:
return
prev = history[-2]
curr = history[-1]
if prev.price and curr.price:
change_pct = ((curr.price - prev.price) / prev.price) * 100
if abs(change_pct) >= 5: # 5% threshold
self.send_alert(url, prev.price, curr.price, change_pct)
# Stock status change
if prev.in_stock and not curr.in_stock:
self.send_alert(url, msg="Product went out of stock")
elif not prev.in_stock and curr.in_stock:
self.send_alert(url, msg="Product back in stock")
def send_alert(self, url, old_price=None, new_price=None,
change_pct=None, msg=None):
"""Send price change notification."""
if msg:
print(f"ALERT [{url}]: {msg}")
else:
direction = "dropped" if change_pct < 0 else "increased"
print(f"ALERT [{url}]: Price {direction} {abs(change_pct):.1f}% "
f"(${old_price} -> ${new_price})")
def run(self):
"""Start the monitoring loop."""
while True:
schedule.run_pending()
time.sleep(1)
# Usage
if __name__ == "__main__":
monitor = PriceMonitor(db_connection=None) # Replace with actual DB
# Monitor competitor products
monitor.add_product(
"https://www.amazon.com/dp/B0CHX3QBCH",
site="amazon.com",
check_interval_minutes=60,
)
monitor.add_product(
"https://www.amazon.com/dp/B0D5BKRY4R",
site="amazon.com",
check_interval_minutes=30, # Higher priority
)
monitor.run()Node.js Attuazione
Per le squadre che utilizzano Node.js, ecco una configurazione di monitoraggio equivalente utilizzando SDK del nodo di ProxyHat.
const axios = require("axios");
const cheerio = require("cheerio");
const { HttpsProxyAgent } = require("https-proxy-agent");
const cron = require("node-cron");
const PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080";
const agent = new HttpsProxyAgent(PROXY_URL);
const USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
];
async function scrapePrice(url, selectors) {
try {
const { data } = await axios.get(url, {
httpsAgent: agent,
headers: {
"User-Agent": USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],
"Accept-Language": "en-US,en;q=0.9",
},
timeout: 30000,
});
const $ = cheerio.load(data);
const priceText = $(selectors.price).first().text().trim();
const price = parseFloat(priceText.replace(/[^0-9.]/g, "")) || null;
return {
url,
price,
currency: selectors.currency || "USD",
inStock: $(selectors.stock).text().toLowerCase().includes("in stock"),
scrapedAt: new Date().toISOString(),
};
} catch (err) {
return { url, price: null, currency: null, inStock: false, scrapedAt: new Date().toISOString() };
}
}
class PriceMonitor {
constructor() {
this.products = [];
this.history = new Map();
}
addProduct(url, selectors, cronExpression = "0 * * * *") {
this.products.push({ url, selectors, cronExpression });
this.history.set(url, []);
cron.schedule(cronExpression, async () => {
const result = await scrapePrice(url, selectors);
const prev = this.history.get(url);
prev.push(result);
if (prev.length >= 2) {
const last = prev[prev.length - 2];
if (last.price && result.price) {
const changePct = ((result.price - last.price) / last.price) * 100;
if (Math.abs(changePct) >= 5) {
console.log(`ALERT [${url}]: Price changed ${changePct.toFixed(1)}%`);
}
}
}
console.log(`Checked ${url}: $${result.price} (${result.inStock ? "in stock" : "out of stock"})`);
});
}
}
// Usage
const monitor = new PriceMonitor();
monitor.addProduct(
"https://www.amazon.com/dp/B0CHX3QBCH",
{ price: "span.a-price-whole", stock: "#availability span", currency: "USD" },
"0 * * * *" // Every hour
);
monitor.addProduct(
"https://www.amazon.com/dp/B0D5BKRY4R",
{ price: "span.a-price-whole", stock: "#availability span", currency: "USD" },
"*/30 * * * *" // Every 30 minutes
);Memorizzazione e analisi dei dati
I dati dei prezzi grezzi diventano preziosi quando è possibile analizzare le tendenze nel tempo.
Schema del database
CREATE TABLE monitored_products (
id SERIAL PRIMARY KEY,
url TEXT NOT NULL,
site VARCHAR(100) NOT NULL,
product_name VARCHAR(500),
our_sku VARCHAR(100),
check_interval_minutes INT DEFAULT 60,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE price_history (
id SERIAL PRIMARY KEY,
product_id INT REFERENCES monitored_products(id),
price DECIMAL(10, 2),
currency VARCHAR(3) DEFAULT 'USD',
in_stock BOOLEAN,
scraped_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_price_history_product_time
ON price_history (product_id, scraped_at DESC);Quesiti di tendenza dei prezzi
-- Average daily price for the last 30 days
SELECT
date_trunc('day', scraped_at) AS day,
AVG(price) AS avg_price,
MIN(price) AS min_price,
MAX(price) AS max_price
FROM price_history
WHERE product_id = 1
AND scraped_at >= now() - INTERVAL '30 days'
GROUP BY day
ORDER BY day;
-- Products with price drops > 10% in the last 24 hours
SELECT
mp.product_name,
mp.url,
old_prices.avg_price AS price_yesterday,
new_prices.avg_price AS price_today,
((new_prices.avg_price - old_prices.avg_price) / old_prices.avg_price * 100) AS change_pct
FROM monitored_products mp
JOIN LATERAL (
SELECT AVG(price) AS avg_price
FROM price_history
WHERE product_id = mp.id
AND scraped_at BETWEEN now() - INTERVAL '48 hours' AND now() - INTERVAL '24 hours'
) old_prices ON true
JOIN LATERAL (
SELECT AVG(price) AS avg_price
FROM price_history
WHERE product_id = mp.id
AND scraped_at >= now() - INTERVAL '24 hours'
) new_prices ON true
WHERE ((new_prices.avg_price - old_prices.avg_price) / old_prices.avg_price * 100) < -10;Alerting e Notifiche
Gli avvisi automatizzati garantiscono di reagire rapidamente ai cambiamenti dei prezzi. I canali comuni di notifica includono:
- Slack webhooks: Ideale per la visibilità in tutto il team. Invia messaggi strutturati con dettagli cambio prezzo.
- Email digests: Riepilogo giornaliero o oraria di tutti i cambiamenti di prezzo sopra la soglia.
- Webhook: Trigger il motore di ripetizione o altra automazione quando i prezzi cambiano.
- Dashboard: Visualizzazione in tempo reale delle tendenze dei prezzi in tutti i prodotti monitorati.
Alert Thresholds
Configurare diverse soglie di allarme per diversi scenari:
| Scenario | Soglia | Azione |
|---|---|---|
| Riduzione del prezzo competitivo > 5% | 5% | Slack notifica |
| Riduzione del prezzo competitivo > 15% | 15% | Email a pricing team + auto-riprezzo |
| Prodotto esaurito | Variazione delle scorte | Avviso di opportunità |
| Prezzo sotto MAP | Sotto il valore MAP | Avviso di conformità |
Migliori pratiche proxy per il monitoraggio
Il monitoraggio continuo crea sfide uniche per la gestione dei proxy rispetto alla raschiatura di una volta.
- Distribuire richieste nel tempo: Invece di controllare tutti i 10.000 prodotti a mezzanotte, diffondere i controlli attraverso l'intero intervallo. Questo crea un modello di richiesta stabile e a basso profilo.
- Utilizzare i proxy residenziali: Processi residenziali sono essenziali per il monitoraggio a lungo termine perché gli stessi IP del datacenter che colpiscono gli stessi siti al giorno saranno vietati.
- Corrispondenza geolocalizzazione: Durante il monitoraggio dei prezzi regionali, utilizzare i proxy dalla regione di destinazione. Un controllo IP degli Stati Uniti i prezzi tedeschi vedranno i dati errati o verranno reindirizzati.
- Maniglia guasti con grazia: Se una richiesta fallisce, aspetta e riprova con backoff esponenziale piuttosto che immediatamente ri-richiesta. Monitorare il tasso di successo e ridurre la convalutazione se scende.
- Cache e deduplica: Se un prezzo non è cambiato, non memorizzare un record duplicato. Questo mantiene il vostro database magra e rende l'analisi più veloce.
Asporto chiave: il monitoraggio dei prezzi è una maratona, non uno sprint. Progettare il sistema per modelli di richiesta costanti e sostenibili piuttosto che scoppiare rottami.
Scalare il sistema di monitoraggio
Man mano che il catalogo dei prodotti cresce, la scala diventa critica. Ecco i modelli che funzionano:
- Vasca da lavoro: Utilizzare più lavoratori tirando da una coda di lavoro (Redis, RabbitMQ). Ogni lavoratore ha le proprie connessioni proxy e opera in modo indipendente.
- Le code prioritarie: I prodotti ad alto valore vengono controllati prima e più frequentemente. Gli elementi a bassa priorità riempiono la capacità rimanente.
- Programmazione adattiva: Se il prezzo di un prodotto non è cambiato in 7 giorni, ridurre automaticamente la frequenza di controllo. Se è cambiato due volte oggi, aumentare la frequenza.
- Tasso di limitazione per sito: Rispetta i limiti di tasso di ogni sito di destinazione. Amazon, Walmart e nicchia negozi hanno tutte tolleranze diverse.
Per ulteriori informazioni sulle operazioni di raschiamento, controllare la nostra guida su migliori proxy per la raschiatura web nel 2026 ed esplorare Piani di prezzi di ProxyHat per il monitoraggio ad alto volume.
Asporto chiave
- Il monitoraggio automatico dei prezzi richiede un'architettura robusta: gestore URL, motore di demolizione, data store e sistema di allarme.
- I proxy residenziali con rotazione per-richiesta sono essenziali per un monitoraggio continuo senza blocchi.
- Controlli di programma basati sulla priorità — non tutti i prodotti hanno bisogno di monitoraggio oraria.
- Conservare la cronologia dei prezzi in uno schema a misura di tempo per l'analisi della tendenza.
- Configurare le soglie di allarme tiered per bilanciare la reattività con la riduzione del rumore.
- Distribuire richieste in modo uniforme nel tempo per un modello di raschiatura sostenibile e a basso profilo.
Pronto a costruire il sistema di monitoraggio dei prezzi? Inizia con I proxy residenziali di ProxyHat e leggere il nostro e-commerce scraping guida per la strategia completa. Per informazioni sull'implementazione tecnica, consulta le nostre guide usando i proxy in Python e usando i proxy in Node.js.






