Surveillance des prix géo-ciblée : suivre les prix à travers les marchés

Surveiller les prix des produits sur les marchés mondiaux en utilisant des procurations géo-cibles. Code Python et Node.js pour la comparaison des prix sur plusieurs marchés, la normalisation des devises et la détection de la stratégie de tarification des concurrents.

Surveillance des prix géo-ciblée : suivre les prix à travers les marchés

Pourquoi les prix varient selon l'emplacement

Les sociétés de commerce électronique ajustent systématiquement les prix en fonction de l'emplacement géographique du client. Un produit qui coûte 49,99 $ aux États-Unis pourrait être évalué à 59,99 EUR en Allemagne, 5 499 JPY au Japon, ou 39,99 $ en Inde. Ces différences vont au-delà de la conversion des devises — elles reflètent le pouvoir d'achat régional, des paysages concurrentiels, des taxes, des coûts d'expédition et des stratégies de tarification délibérées.

Pour l'intelligence concurrentielle, il est essentiel de comprendre ces variations régionales des prix. Un concurrent pourrait être agressivement sous-cotation vous sur un marché tout en payant des prix premium dans un autre. Sans surveillance géo-cible, vous êtes aveugle à la moitié de l'image compétitive. Ce guide traite de la façon de construire un système de surveillance des prix multimarchés à l'aide de procurations géo-cibles. Pour une architecture de surveillance fondamentale, voir notre guide sur surveiller automatiquement les prix des concurrents.

Fonctionnement du système de géo-facturation

Les sites Web déterminent votre emplacement par plusieurs signaux et ajustent le contenu en conséquence.

Fonctionnement du système de géo-facturation
SignalComment ça marcheImpact sur la tarification
Géolocalisation IPAdresse IP cartographiée vers un pays ou une ville au moyen de bases de donnéesFacteur principal — détermine le magasin régional/prix que vous voyez
Monnaie/LangueNavigateur Accept-Langue et sélections antérieuresPeut déclencher un catalogue et un prix spécifiques à une région
CookiesSélections de régions précédentes stockées dans la sessionDépasse la détection par IP lors de visites ultérieures
Structure de l'URLDomaines par pays (amazon.de) ou chemins (/de/)Déterminer directement le catalogue régional
Emplacement GPS/dispositifServices de localisation des appareils mobilesUtilisé pour les prix hyperlocal (zones de livraison)

Modèles communs de géo-facturation

  • Localisation du marché : Amazon, eBay et des plateformes similaires exploitent des vitrines régionales séparées avec des prix indépendants.
  • Géographie dynamique : Les entreprises SaaS et les sites de voyage ajustent les prix en fonction du pays d'origine du visiteur.
  • Prix ajusté pour l'expédition: Les produits incluent différents coûts d'expédition en fonction de l'emplacement, changer le prix effectif.
  • Prix TTC: Les prix européens comprennent généralement la TVA, tandis que les prix américains indiquent les montants avant impôts.
  • Parité de pouvoir d'achat: Certaines entreprises offrent des prix plus bas sur les marchés en développement pour maximiser l'accessibilité.

Configuration mandataire pour la surveillance multi-marchés

L'exigence fondamentale est la proximité résidentielle de chaque pays cible. Le géo-ciblage de ProxyHat vous permet de spécifier le pays exact pour chaque demande.

Configuration ProxyHat

# US pricing
http://USERNAME-country-US:PASSWORD@gate.proxyhat.com:8080
# German pricing
http://USERNAME-country-DE:PASSWORD@gate.proxyhat.com:8080
# UK pricing
http://USERNAME-country-GB:PASSWORD@gate.proxyhat.com:8080
# Japanese pricing
http://USERNAME-country-JP:PASSWORD@gate.proxyhat.com:8080
# Brazilian pricing
http://USERNAME-country-BR:PASSWORD@gate.proxyhat.com:8080
# City-level targeting for hyperlocal pricing
http://USERNAME-country-US-city-newyork:PASSWORD@gate.proxyhat.com:8080
http://USERNAME-country-DE-city-berlin:PASSWORD@gate.proxyhat.com:8080

Pour la surveillance des prix entre les régions, utiliser la rotation par demande à l'intérieur de chaque pays pour éviter la détection, mais toujours maintenir un ciblage géographique uniforme par marché. Vérifier Liste complète des emplacements de ProxyHat pour plus de 195 pays soutenus.

Mise en œuvre de Python

Voici un système de surveillance des prix multi-marchés utilisant Python SDK de ProxyHat.

Gratte-prix géo-targeté

import requests
from bs4 import BeautifulSoup
import json
import time
import random
from dataclasses import dataclass, asdict
from datetime import datetime
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",
]
PROXY_TEMPLATE = "http://USERNAME-country-{country}:PASSWORD@gate.proxyhat.com:8080"
@dataclass
class GeoPrice:
    product_id: str
    country: str
    price: float | None
    currency: str
    url: str
    in_stock: bool
    scraped_at: str
def get_geo_proxy(country_code: str) -> dict:
    """Get proxy configured for a specific country."""
    proxy = PROXY_TEMPLATE.format(country=country_code)
    return {"http": proxy, "https": proxy}
def scrape_price_for_region(product_url: str, country_code: str,
                             price_selector: str, currency: str) -> GeoPrice:
    """Scrape a product price from a specific geographic region."""
    headers = {
        "User-Agent": random.choice(USER_AGENTS),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": get_accept_language(country_code),
    }
    proxies = get_geo_proxy(country_code)
    try:
        response = requests.get(product_url, headers=headers,
                                proxies=proxies, timeout=30)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, "html.parser")
        price_el = soup.select_one(price_selector)
        price = None
        if price_el:
            price_text = price_el.get_text(strip=True)
            cleaned = "".join(c for c in price_text if c.isdigit() or c in ".,")
            # Handle European comma as decimal separator
            if "," in cleaned and "." in cleaned:
                cleaned = cleaned.replace(".", "").replace(",", ".")
            elif "," in cleaned:
                cleaned = cleaned.replace(",", ".")
            price = float(cleaned) if cleaned else None
        return GeoPrice(
            product_id=product_url,
            country=country_code,
            price=price,
            currency=currency,
            url=product_url,
            in_stock=True,
            scraped_at=datetime.utcnow().isoformat(),
        )
    except Exception as e:
        return GeoPrice(
            product_id=product_url,
            country=country_code,
            price=None,
            currency=currency,
            url=product_url,
            in_stock=False,
            scraped_at=datetime.utcnow().isoformat(),
        )
def get_accept_language(country_code: str) -> str:
    """Return appropriate Accept-Language for a country."""
    lang_map = {
        "US": "en-US,en;q=0.9",
        "GB": "en-GB,en;q=0.9",
        "DE": "de-DE,de;q=0.9,en;q=0.5",
        "FR": "fr-FR,fr;q=0.9,en;q=0.5",
        "JP": "ja-JP,ja;q=0.9,en;q=0.5",
        "BR": "pt-BR,pt;q=0.9,en;q=0.5",
        "IN": "en-IN,hi;q=0.9,en;q=0.5",
        "IT": "it-IT,it;q=0.9,en;q=0.5",
        "ES": "es-ES,es;q=0.9,en;q=0.5",
    }
    return lang_map.get(country_code, "en-US,en;q=0.9")

Moniteur multimarché

class MultiMarketMonitor:
    """Monitor prices across multiple geographic markets."""
    def __init__(self):
        self.markets = {}
        self.results = []
    def add_market(self, country_code: str, marketplace_url: str,
                   price_selector: str, currency: str):
        """Register a market for monitoring."""
        self.markets[country_code] = {
            "url": marketplace_url,
            "selector": price_selector,
            "currency": currency,
        }
    def monitor_product(self, product_urls: dict[str, str]) -> list[GeoPrice]:
        """
        Monitor a product across all configured markets.
        product_urls: {"US": "https://amazon.com/dp/...", "DE": "https://amazon.de/dp/..."}
        """
        prices = []
        for country, url in product_urls.items():
            market = self.markets.get(country)
            if not market:
                continue
            price = scrape_price_for_region(
                url, country,
                market["selector"],
                market["currency"]
            )
            prices.append(price)
            print(f"  {country}: {price.currency} {price.price}")
            time.sleep(random.uniform(2, 5))
        return prices
    def compare_prices(self, prices: list[GeoPrice], base_currency_rates: dict) -> dict:
        """Compare prices across markets normalized to USD."""
        normalized = {}
        for p in prices:
            if p.price:
                rate = base_currency_rates.get(p.currency, 1.0)
                normalized[p.country] = {
                    "local_price": p.price,
                    "currency": p.currency,
                    "usd_equivalent": round(p.price / rate, 2),
                }
        if not normalized:
            return {}
        usd_prices = [v["usd_equivalent"] for v in normalized.values()]
        cheapest = min(usd_prices)
        most_expensive = max(usd_prices)
        return {
            "prices": normalized,
            "cheapest_market": [k for k, v in normalized.items()
                                if v["usd_equivalent"] == cheapest][0],
            "most_expensive_market": [k for k, v in normalized.items()
                                      if v["usd_equivalent"] == most_expensive][0],
            "price_spread_pct": round(
                (most_expensive - cheapest) / cheapest * 100, 1
            ) if cheapest > 0 else 0,
        }
# Example: Monitor a product across Amazon marketplaces
monitor = MultiMarketMonitor()
# Configure markets
monitor.add_market("US", "amazon.com", "span.a-price-whole", "USD")
monitor.add_market("DE", "amazon.de", "span.a-price-whole", "EUR")
monitor.add_market("GB", "amazon.co.uk", "span.a-price-whole", "GBP")
monitor.add_market("JP", "amazon.co.jp", "span.a-price-whole", "JPY")
# Monitor a specific product
prices = monitor.monitor_product({
    "US": "https://www.amazon.com/dp/B0CHX3QBCH",
    "DE": "https://www.amazon.de/dp/B0CHX3QBCH",
    "GB": "https://www.amazon.co.uk/dp/B0CHX3QBCH",
    "JP": "https://www.amazon.co.jp/dp/B0CHX3QBCH",
})
# Compare prices in USD
comparison = monitor.compare_prices(prices, {
    "USD": 1.0, "EUR": 0.92, "GBP": 0.79, "JPY": 149.5,
})
print(json.dumps(comparison, indent=2))

Mise en œuvre de Node.js

Un moniteur multimarché Node.js utilisant Le nœud SDK de ProxyHat.

const axios = require("axios");
const cheerio = require("cheerio");
const { HttpsProxyAgent } = require("https-proxy-agent");
function getGeoProxy(countryCode) {
  return `http://USERNAME-country-${countryCode}:PASSWORD@gate.proxyhat.com:8080`;
}
const LANG_MAP = {
  US: "en-US,en;q=0.9",
  GB: "en-GB,en;q=0.9",
  DE: "de-DE,de;q=0.9,en;q=0.5",
  FR: "fr-FR,fr;q=0.9,en;q=0.5",
  JP: "ja-JP,ja;q=0.9,en;q=0.5",
};
async function scrapeGeoPrice(url, countryCode, priceSelector, currency) {
  const agent = new HttpsProxyAgent(getGeoProxy(countryCode));
  try {
    const { data } = await axios.get(url, {
      httpsAgent: agent,
      headers: {
        "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
        "Accept-Language": LANG_MAP[countryCode] || "en-US,en;q=0.9",
      },
      timeout: 30000,
    });
    const $ = cheerio.load(data);
    let priceText = $(priceSelector).first().text().trim();
    let price = parseFloat(priceText.replace(/[^0-9.,]/g, "").replace(",", ".")) || null;
    return {
      country: countryCode,
      price,
      currency,
      url,
      inStock: true,
      scrapedAt: new Date().toISOString(),
    };
  } catch (err) {
    return { country: countryCode, price: null, currency, url, inStock: false, scrapedAt: new Date().toISOString() };
  }
}
async function monitorMultiMarket(productUrls, markets) {
  const results = [];
  for (const [country, url] of Object.entries(productUrls)) {
    const market = markets[country];
    if (!market) continue;
    const result = await scrapeGeoPrice(url, country, market.selector, market.currency);
    results.push(result);
    console.log(`${country}: ${result.currency} ${result.price}`);
    await new Promise((r) => setTimeout(r, 2000 + Math.random() * 3000));
  }
  return results;
}
function comparePrices(results, rates) {
  const normalized = {};
  for (const r of results) {
    if (r.price) {
      const rate = rates[r.currency] || 1;
      normalized[r.country] = {
        localPrice: r.price,
        currency: r.currency,
        usdEquivalent: Math.round((r.price / rate) * 100) / 100,
      };
    }
  }
  const usdPrices = Object.values(normalized).map((v) => v.usdEquivalent);
  const cheapest = Math.min(...usdPrices);
  const mostExpensive = Math.max(...usdPrices);
  return {
    prices: normalized,
    cheapestMarket: Object.keys(normalized).find((k) => normalized[k].usdEquivalent === cheapest),
    mostExpensiveMarket: Object.keys(normalized).find(
      (k) => normalized[k].usdEquivalent === mostExpensive
    ),
    priceSpreadPct: cheapest > 0 ? Math.round(((mostExpensive - cheapest) / cheapest) * 1000) / 10 : 0,
  };
}
// Usage
const markets = {
  US: { selector: "span.a-price-whole", currency: "USD" },
  DE: { selector: "span.a-price-whole", currency: "EUR" },
  GB: { selector: "span.a-price-whole", currency: "GBP" },
  JP: { selector: "span.a-price-whole", currency: "JPY" },
};
monitorMultiMarket(
  {
    US: "https://www.amazon.com/dp/B0CHX3QBCH",
    DE: "https://www.amazon.de/dp/B0CHX3QBCH",
    GB: "https://www.amazon.co.uk/dp/B0CHX3QBCH",
    JP: "https://www.amazon.co.jp/dp/B0CHX3QBCH",
  },
  markets
).then((results) => {
  const comparison = comparePrices(results, { USD: 1.0, EUR: 0.92, GBP: 0.79, JPY: 149.5 });
  console.log(JSON.stringify(comparison, null, 2));
});

Stratégies de surveillance multimarchés

Normalisation des monnaies

Pour comparer les prix de façon significative, normaliser tous les prix en une monnaie de base. Utilisez une API de taux de change fiable (taux de change ouverts, taux de la BCE) et mettez à jour quotidiennement les taux. Conservez les prix locaux et normalisés pour une analyse historique précise.

Traitement fiscal

Les prix sur différents marchés incluent différents niveaux d'imposition:

Traitement fiscal
MarchéTraitement fiscal typiqueExamen
États-UnisPrix affichés avant impôtsLe coût réel varie selon l'état (0-10,25%)
Union européenneLes prix comprennent la TVA (19-27%)Soustrayez la TVA pour une comparaison similaire
Royaume-UniLes prix incluent 20% de TVASoustraire la TVA à la comparaison nette
JaponLes prix incluent 10% de taxe de consommationImpôt de soustraction pour comparaison nette

Calendrier de surveillance

Tous les marchés n'ont pas besoin de la même fréquence de contrôle. Priorité en fonction de l'impact des entreprises :

  • Marchés primaires: Vos principales régions de vente — vérifiez toutes les 1 à 2 heures.
  • Objectifs d'expansion: Les marchés que vous entrez — vérifiez toutes les 4-6 heures.
  • Marchés de référence: Marchés pour l'étalonnage des performances uniquement — contrôle quotidien.

Détecter les stratégies de géo-facturation

Avec les données multimarchés, vous pouvez identifier les stratégies de tarification des concurrents:

  • Prix mondiaux uniformes: Même prix (après conversion des devises) partout. Commun pour les produits numériques.
  • Prix corrigé des PPA: Des prix plus bas sur les marchés à faible revenu. Commun pour SaaS et logiciels.
  • Prix axés sur la concurrence: Les prix varient selon le marché en fonction de la pression concurrentielle locale.
  • Prix plus élevé: Différents prix reflétant différents frais de transport, d'entreposage et de taxes.
Le suivi multi-marchés révèle des stratégies de prix invisibles à l'analyse du marché unique. Un concurrent offrant des prix inférieurs de 30 % sur un marché indique une expansion agressive ou une structure de coûts différente qui mérite d'être étudiée.

Faire face aux défis communs

Réorientations régionales

Certains sites redirigent les utilisateurs vers des versions régionales basées sur l'IP. Avec les proxies géo-cibles, vous voulez cette redirection — il vous amène à la tarification régionale correcte. Ne suivez pas les redirections transrégionales, car elles indiquent que l'emplacement IP ne correspond pas au marché cible.

Différences de contenu

La disponibilité du produit varie selon les régions. Un produit vendu sur amazon.com pourrait ne pas exister sur amazon.de. Gérez 404 réponses et produits non disponibles gracieusement dans votre pipeline de surveillance.

Étiquette

Lorsque vous surveillez plusieurs régions, vous supprimez efficacement plusieurs sites Web distincts. Appliquer bonnes pratiques pour éviter les blocs indépendant par marché. Ce qui fonctionne pour amazon.com peut nécessiter un réglage différent pour amazon.co.jp.

Stockage des données pour les données multi-marchés

CREATE TABLE geo_price_history (
    id SERIAL PRIMARY KEY,
    product_id VARCHAR(100) NOT NULL,
    country_code VARCHAR(2) NOT NULL,
    local_price DECIMAL(12, 2),
    currency VARCHAR(3),
    usd_equivalent DECIMAL(12, 2),
    exchange_rate DECIMAL(10, 6),
    in_stock BOOLEAN,
    scraped_at TIMESTAMPTZ NOT NULL,
    created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_geo_price_product_country
    ON geo_price_history (product_id, country_code, scraped_at DESC);
-- Query: Price spread across markets for a product
SELECT
    country_code,
    AVG(usd_equivalent) AS avg_usd_price,
    MIN(usd_equivalent) AS min_usd_price,
    MAX(usd_equivalent) AS max_usd_price
FROM geo_price_history
WHERE product_id = 'B0CHX3QBCH'
  AND scraped_at >= now() - INTERVAL '7 days'
GROUP BY country_code
ORDER BY avg_usd_price;

A emporter des clés

  • Les prix du commerce électronique varient considérablement selon la géographie — le suivi d'un marché donne une image incomplète de la concurrence.
  • Les procurations résidentielles géo-cibles sont essentielles : utiliser le ciblage national de ProxyHat pour accéder à des prix régionaux authentiques.
  • Normaliser les prix en une monnaie de base pour des comparaisons significatives entre les marchés.
  • Comptabiliser les différences fiscales (TVA incluses par rapport à la prétaxe) lors de la comparaison des prix.
  • Corriger les en-têtes Accept-Langue au pays cible pour des résultats précis.
  • Prioriser la fréquence de surveillance par importance sur le marché pour optimiser l'utilisation des procurations.

Prêt à surveiller les prix sur tous les marchés? Commencez par Proxies résidentielles de ProxyHat avec 195+ options pays et lire notre Guide sur la démolition du commerce électronique pour la stratégie complète. Pour les capacités en temps réel, voir notre guide sur infrastructure de surveillance des prix en temps réel.

Prêt à commencer ?

Accédez à plus de 50M d'IPs résidentielles dans plus de 148 pays avec filtrage IA.

Voir les tarifsProxies résidentiels
← Retour au Blog