Geocelowany monitoring cen: ceny ścieżek na rynkach

Monitorowanie cen produktów na rynkach światowych przy użyciu proxy ukierunkowanej na geologię. Python i Node.js kod do wielorynkowe porównanie cen, normalizacja waluty i wykrywanie strategii cenowej konkurentów.

Geocelowany monitoring cen: ceny ścieżek na rynkach

Dlaczego ceny Differ według lokalizacji

Firmy handlu elektronicznego rutynowo dostosowują ceny w oparciu o położenie geograficzne klienta. Produkt, który kosztuje 49,99 dolarów w Stanach Zjednoczonych może być w cenie 59,99 EUR w Niemczech, 5,499 JPY w Japonii, lub 39,99 dolarów w Indiach. Różnice te wykraczają poza przeliczanie walut - odzwierciedlają one regionalną siłę nabywczą, konkurencyjne krajobrazy, podatki, koszty transportu i celowe strategie cenowe.

Dla uzyskania konkurencyjnej inteligencji, zrozumienie tych regionalnych wahań cen ma kluczowe znaczenie. Konkurent może agresywnie podcinać cię na jednym rynku, a ceny premium na innym. Bez monitorowania geologicznego jesteś ślepy na połowę konkurencyjnego obrazu. Niniejszy przewodnik obejmuje sposób budowy systemu monitorowania cen na wielu rynkach za pomocą geodocelowych proxy. Architektura monitoringu fundamentalnego, zobacz nasz przewodnik Automatyczne monitorowanie cen konkurencyjnych.

Jak działa cena geo-

Strony internetowe określają lokalizację poprzez kilka sygnałów i odpowiednio dostosowują zawartość.

SygnałJak to działaWpływ na ceny
Geolokalizacja IPAdres IP odwzorowany na kraj / miasto poprzez bazy danychCzynnik podstawowy - określa, który sklep regionalny / ceny widzisz
Waluta / JęzykPrzeglądarka Akcept- Język i poprzedni wybórMoże wywołać specyficzny dla regionu katalog i ceny
CiasteczkaPoprzedni wybór regionu zapisany w sesjiNadwyżka wykrywalności IP- na podstawie kolejnych wizyt
Struktura URLDomeny lokalne (amazon.de) lub ścieżki (/ de /)Bezpośrednio określa katalog regionalny
Lokalizacja GPS / urządzeniaUsługi lokalizacji urządzeń mobilnychWykorzystywane do ustalania cen hiperlokalnych (strefy dostaw)

Wspólne wzory geocenowe

  • Lokalizacja rynku: Amazon, eBay i podobne platformy prowadzą oddzielne regionalne sklepy z niezależnymi cenami.
  • Dynamiczna geocena: Firmy SaaS i biura podróży dostosowują ceny w zależności od kraju pochodzenia odwiedzającego.
  • Wyceny skorygowane o koszty wysyłki: Produkty obejmują różne koszty wysyłki w zależności od lokalizacji, zmieniając efektywną cenę.
  • Ceny obejmujące podatki: Ceny europejskie zazwyczaj obejmują VAT, podczas gdy ceny w USA wykazują kwoty przed opodatkowaniem.
  • parytet siły nabywczej: Niektóre firmy oferują niższe ceny na rynkach rozwijających się w celu maksymalizacji dostępności.

Konfiguracja Proxy do monitorowania wielorynkowego

Podstawowym wymogiem jest proxy mieszkaniowe z każdego kraju docelowego. Geocelowanie ProxyHat pozwala określić dokładny kraj dla każdej prośby.

Ustawienia 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

W odniesieniu do monitorowania cen w poszczególnych regionach należy stosować rotację na żądanie w każdym kraju, aby uniknąć wykrycia, ale zawsze utrzymywać spójne ukierunkowanie geologiczne na rynek. Sprawdź Pełna lista lokalizacji ProxyHat dla 195 + wspieranych krajów.

Wdrażanie Pythona

Oto wielorynkowy system monitorowania cen za pomocą Python SDK ProxyHat.

Geocelowane scrapper cena

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")

Monitor wielorynkowy

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))

Wdrażanie Node.js

Monitor wielorynkowy Node.js Węzeł ProxyHat SDK.

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));
});

Strategie wielostronnego monitorowania rynku

Normalizacja waluty

Aby porównać ceny znacząco, normalizować wszystkie ceny do waluty bazowej. Korzystanie z niezawodnego API kursu wymiany (Open Exchange Rates, ECB rates) i aktualizować kursy codziennie. Przechowuj zarówno lokalne jak i znormalizowane ceny dla dokładnej analizy historycznej.

Obsługa podatkowa

Ceny na różnych rynkach obejmują różne poziomy opodatkowania:

RynekTypowe traktowanie podatkoweRozważanie
Stany ZjednoczoneCeny wykazane przed opodatkowaniemRzeczywisty koszt różni się według stanu (0- 10,25%)
Unia EuropejskaCeny obejmują VAT (19- 27%)Odjąć VAT dla porównania podobnego do
Zjednoczone KrólestwoCeny zawierają 20% VATOdjąć VAT od porównania netto
JaponiaCeny zawierają 10% podatku konsumpcyjnegoPodatek od odejmowania od porównania netto

Schemat monitorowania

Nie wszystkie rynki potrzebują tej samej częstotliwości kontroli. Priorytet oparty na wpływie działalności gospodarczej:

  • Rynki podstawowe: Twoje główne regiony sprzedaży - sprawdź co 1-2 godziny.
  • Cele rozszerzenia: Rynki, na które wchodzisz - sprawdzaj co 4- 6 godzin.
  • Rynki referencyjne: Tylko rynki benchmarkingu - sprawdź codziennie.

Wykrywanie strategii wyceny geocenowej

Dane z wielu rynków umożliwiają identyfikację konkurencyjnych strategii cenowych:

  • Jednolite ceny globalne: Ta sama cena (po przeliczeniu walut) wszędzie. Wspólne dla produktów cyfrowych.
  • Ceny dostosowane do PPP: Niższe ceny na rynkach niższych dochodów. Wspólne dla SaaS i oprogramowania.
  • Ceny oparte na konkurencji: Ceny różnią się w zależności od rynku w zależności od lokalnej presji konkurencyjnej.
  • Ceny Cost- plus: Różne ceny odzwierciedlające różne koszty wysyłki, magazynowania i podatków.
Kluczowe podejście: Wielorynkowe monitorowanie ujawnia strategie cenowe niewidoczne dla analizy rynku pojedynczego. Konkurent oferujący 30% niższe ceny na jednym rynku sygnalizuje agresywną ekspansję lub inną strukturę kosztów wartą zbadania.

Rozwiązywanie wspólnych wyzwań

Przekierowanie regionalne

Niektóre strony przekierowują użytkowników do regionalnych wersji opartych na IP. Z geocelowymi proxy, chcesz to przekierować - to prowadzi do prawidłowej regionalnej ceny. Nie podążaj za przekierowaniem międzyregionalnym, ponieważ wskazują one, że lokalizacja IP nie odpowiada rynkowi docelowemu.

Różnice zawartości

Dostępność produktów różni się w zależności od regionu. Produkt sprzedawany na Amazon.com może nie istnieć na Amazon.de. Obsługuj 404 odpowiedzi i niedostępne produkty z wdziękiem w swoim rurociągu monitorującym.

Scraping Etiquette

Monitorując wiele regionów, skutecznie skrobiesz wiele oddzielnych stron internetowych. Zastosuj najlepsze praktyki unikania bloków niezależnie od rynku. Co działa dla amazon.com może potrzebować innego strojenia dla amazon.co.jp.

Przechowywanie danych dla danych wielorynkowych

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;

Key Takeaways

  • Ceny handlu elektronicznego znacznie się różnią w zależności od położenia geograficznego - monitorowanie jednego rynku daje niekompletny obraz konkurencji.
  • Geoukierunkowane proxy mieszkaniowe są niezbędne: należy wykorzystać poziom krajowy ProxyHat ukierunkowany na dostęp do autentycznych cen regionalnych.
  • Normalizacja cen do waluty bazowej dla znaczących porównań rynku.
  • Przy porównywaniu cen należy uwzględnić różnice podatkowe (VAT- inclusive vs pre- tax).
  • Dopasuj nagłówki akcept- Język do kraju docelowego, aby uzyskać dokładne wyniki.
  • Priorytetowa częstotliwość monitorowania według znaczenia rynku w celu optymalizacji wykorzystania proxy.

Gotowy do monitorowania cen na rynkach? Zacznij od ProxyHat 's residential proxy z 195 + opcji kraju i przeczytać nasz Przewodnik po e-handlu dla pełnej strategii. Dla real- time możliwości, zobacz nasz przewodnik na infrastruktura monitorowania cen w czasie rzeczywistym.

Gotowy, aby zacząć?

Dostęp do ponad 50 mln rezydencjalnych IP w ponad 148 krajach z filtrowaniem AI.

Zobacz cenyProxy rezydencjalne
← Powrót do Bloga