ジオターゲット価格監視:マーケット横断の価格追跡

ジオターゲティングプロキシを使用して、グローバル市場全体の製品価格を監視します。 Python と Node.js のコードは、マルチマーケット価格比較、通貨の正規化、競合者の価格設定戦略の検出に使用されます.

ジオターゲット価格監視:マーケット横断の価格追跡

なぜ場所によって価格の差分

顧客の地理的な位置に基づいて価格を規則的に調整するEコマース企業。 米国で$ 49.99の費用がかかる製品は、ドイツで$ 59.99 EUR、日本では5,499 JPY、インドでは$ 39.99で販売されている可能性があります。 これらの違いは、通貨の変換を超えて行きます — 彼らは地域の購買力、競争力のある風景、税金、配送コスト、および審美的な価格設定戦略を反映しています。

競争力のあるインテリジェンスのために、これらの地域の価格の変動を理解することは重要です。 競合他社は、別のプレミアム価格を充電しながら、1つの市場であなたを積極的にアンダーカットする可能性があります。 ジオターゲティングされた監視なしで、あなたは半分の競争力のある画像に盲目です。 ジオターゲティングプロキシを使用して、マルチマーケット価格監視システムを構築する方法について説明します。 基礎監視アーキテクチャについては、ガイドをご覧ください 競争相手の価格を自動的に監視して下さい. .

ジオプライシングの仕組み

ウェブサイトは、複数の信号を介して場所を決定し、それに応じてコンテンツを調整します。

ジオプライシングの仕組み
シグナル仕組み価格への影響
IPジオロケーションデータベースを介して国/市にマッピングされたIPアドレスプライマリファクター — どの地域ストア/プライシングを閲覧するかを判断
通貨/言語ブラウザ 受け入れ言語と以前の選択地域固有のカタログと価格のトリガー
メニューセッションに保存された地域選択その後の訪問でIPベースの検出をオーバーライド
URL構造国別ドメイン(amazon.de)またはパス(/de/)地域カタログを直接決定
GPS /デバイスの場所モバイルデバイスの場所サービスハイパーローカル価格設定(配送ゾーン)に使用されます

一般的なジオプライシングパターン

  • 市場局在化: Amazon、eBay、および同様のプラットフォームは、独立した価格設定で別の地域の店先を操作します。
  • 動的ジオプライシング: SaaS企業と旅行サイトは、訪問者の原産国に基づいて価格を調整します。
  • 船積み調整された価格: プロダクトは有効な価格を変える位置に基づいて別の船積みの費用を、含んでいます。
  • 税込価格: ヨーロッパの価格は一般的にVATを含みます, 一方、米国価格は前税額を示しています.
  • 購入力パリティ: 一部の企業は、アクセス可能性を最大化するために、開発市場で低価格を提供しています。

マルチマーケットモニタリング用のプロキシ構成

コア要件は、各ターゲット国から住宅用プロキシです。 ProxyHatのジオターゲティングでは、リクエストごとに正確な国を指定できます。

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

地域全体の価格監視のために、検出を回避するために、各国内の1回限りのリクエスト回転を使用しますが、常に市場ごとの一貫したジオターゲティングを維持します。 チェックイン ProxyHatのフルロケーションリスト 195以上のサポート対象国

Pythonの実装

ここでは、マルチマーケット価格監視システムを使用しています ProxyHatのPython SDK. .

ジオターゲット価格スクレーパー

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

マルチマーケットモニター

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

Node.js 実装

Node.js マルチマーケットモニター 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));
});

マルチマーケットモニタリング戦略

通貨正規化

つまり価格を比較するために、すべての価格をベース通貨に正規化します。 信頼性の高い為替レートAPI(為替レート、ECBレート)と毎日更新レートを使用してください。 正確な歴史的分析のためにローカルおよび正規化の価格を貯えて下さい。

税務対応

異なる市場での価格には、異なる税レベルが含まれています。

税務対応
マーケット典型的な税務処理導入事例
アメリカ合衆国前税表示価格実際の費用は状態によって変わります(0-10.25%)
欧州連合付加価値税(19-27%)同様の比較のためのVATを抽出
イギリス価格には20%のVATが含まれていますネット比較のためのVATを割く
ジャパンジャパン価格には消費税10%が含まれていますネット比較のための課税

監視スケジュール

すべての市場は同じチェック周波数を必要としません。 ビジネスインパクトに基づく優先順位付け:

  • 第一次市場: 主要な販売地域 — 1-2 時間ごとに確認します。
  • 拡張ターゲット: あなたが入っている市場 - 4-6時間ごとに確認します。
  • 参照の市場: ベンチマークのみの市場—毎日チェック。

ジオプライシング戦略の検出

複数の市場データでは、競合他社の価格設定戦略を識別することができます。

  • 均一全体的な価格: どこでも同じ価格(通貨変換後)。 デジタルプロダクトのために共通。
  • PPP 調整された価格: 低所得市場での価格を下げます。 SaaSとソフトウェアの共通
  • 競争主導の価格: 価格はローカル競争圧力に基づいて市場によって変わります。
  • コストプラスの価格: 異なる配送、倉庫、および税金コストを反映した異なる価格。
主要なテイクアウト: 複数の市場の監視は単価分析に見えない価格設定戦略を明らかにします。. 1つの市場信号で30%の低価格を提供する競合他社は、攻撃的な拡張または投資価値のある別のコスト構造のいずれか。

共通の課題の解決

地域リダイレクト

一部のサイトでは、IP に基づいてユーザーを地域のバージョンにリダイレクトします。 ジオターゲティングプロキシを使用すると、このリダイレクトを望む - それは正しい地域の価格設定にかかります。 ターゲット市場と一致しない IP 位置を示すため、交差領域リダイレクトに従わない。

コンテンツの違い

地域により商品が異なります。 amazon.comで販売されている製品はamazon.deに存在しません。 404の応答を扱い、あなたの監視パイプラインで十分に利用できなくなったプロダクト。

スクレイピングエチケット

複数の地域を監視する際には、複数の別のウェブサイトを効果的にスクレイピングします。 お問い合わせ ブロックを避けるためのベストプラクティス 市場ごとの独立。 amazon.comの作品は、amazon.co.jpの異なるチューニングが必要な場合があります。

マルチマーケットデータのデータストレージ

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;

キーテイクアウト

  • E-コマース価格は地理によって大きく異なります — 1つの市場を監視すると、不完全な競争力のある画像が得られます。
  • ジオターゲティングされた住宅用プロキシは不可欠です: ProxyHat の国レベルのターゲティングを使用して、本格的な地域価格設定にアクセスします。
  • 意味のあるクロスマーケットの比較のためのベース通貨に価格を正規化.
  • 価格を比較するときの税差(VAT-inclusive対前税)のアカウント。
  • 正確な結果を得るために、受諾言語ヘッダーをターゲット国にマッチさせます。
  • プロキシの使用を最適化する市場重要性によって監視頻度を優先します。

市場全体の価格を監視する準備はできましたか? まずは ProxyHatの住宅用プロキシ 195以上の国のオプションで、 eコマーススクレイピングガイド 完全な戦略のため。 リアルタイム機能については、ガイドをご覧ください リアルタイム価格監視インフラ. .

始める準備はできましたか?

AIフィルタリングで148か国以上、5,000万以上のレジデンシャルIPにアクセス。

料金を見るレジデンシャルプロキシ
← ブログに戻る