パリのホテル室がBooking.comで€200と表示されているが、フランスのIPからアクセスした場合と、同じブラウザで同じURLを米国のIPからアクセスした場合、€260になる。これは通貨換算のアーティファクトではなく、地理位置情報に基づく意図的な動的価格設定である。SaaSの場合、SlackやJiraの同じシートが米国とインドで40%も異なることがある。これらの価格差を大規模に監視するには、航空会社やクラウドベンダーがスクレイパーに対して展開しているのと同じ不正対策システムを生き残るプロキシインフラが必要である。
同じSKUが国境を越えて異なる価格になる理由
地理的裁定取引の価格設定には3つのメカニズムがある。第一に、隠れたマークアップを含む通貨換算——ホテルの予約エンジンは国によって異なる3-5%の為替スプレッドを適用する。第二に、現地の税制:EUのVAT、インドのGST、米国の消費税。第三に、最も積極的な需要ベースの動的価格設定。ブリティッシュ・エアウェイズのロンドンからニューヨークへのフライトは、リクエストが英国のIPから発信された場合、ドイツのIPからよりも高い価格を示す。これは、アルゴリズムが英国の旅行者は支払意欲が高いと想定するためである。AtlassianやSalesforceのようなSaaSベンダーは、地域ごとに別々の価格表を維持しており、新興市場向けには30-50%の割引がよく適用される。これらの価格をプログラムで取得する唯一の方法は、リクエストが各ターゲット市場から来ているように見せかけることである。
複数地域の価格取得のためのプロキシアーキテクチャ
単一のレジデンシャルプロキシプールでは不十分である。国、都市、場合によってはキャリア(例:フランスのモバイルISP対フランスのレジデンシャルDSL)に一致する出口ノードのプールが必要である。標準的なアプローチは、認証済みプロキシのローテーションリストを維持するプロキシブローカーを使用することである。以下は、フランスのプロキシからホテルの価格を取得し、Accept-Languageヘッダーをfr-FRに設定し、最近のChromeビルドからの現実的なUser-Agentを送信する最小限のcurlコマンドである:
curl -s -x "http://user:pass@fr-proxy.example.com:3128" \
-H "Accept-Language: fr-FR,fr;q=0.9" \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" \
"https://www.booking.com/hotel/fr/paris-ritz.html" | grep -oP '"price":"[^"]+"'
この単一のコマンドは、プロキシがDataDomeやAkamaiのようなボット検出サービスに既知である場合、60-80%の確率で失敗する。失敗率が低下するのは、プロキシのローテーションとセッション永続性、およびプロキシの実際のISPに一致するヘッダーフィンガープリンティングを組み合わせた場合のみである。
不正対策ボット検出:真のボトルネック
旅行およびSaaSプラットフォームはボット検出に多額の投資を行っている。IPの評判だけでなく、TLSハンドシェイクフィンガープリント(JA3)、HTTP/2設定、タイミングジッター、HTTPヘッダーの順序もチェックする。あるチェックを通過したプロキシが別のチェックで失敗することがある。例えば、クリーンなIPを持つデータセンタープロキシでも、既知のスクレイピングツールに一致するJA3シグネチャがあると即座にブロックされる。レジデンシャルプロキシも無縁ではない——多くは感染したデバイスから調達され、ブラックリストに載っている。最も効果的な戦略は、ターゲットサイトの検出スタックに対してテスト済みの専用プロキシプールを使用することである。理想的な条件下でも、プロキシあたりの成功率は10-20%と予想される。つまり、安定したスクレイプレート(5-10秒に1リクエスト)を維持するには、ターゲット地域ごとに少なくとも5-10のプロキシが必要である。
ここでトレードオフが顕在化する:高品質のプロキシ(レジデンシャル、静的IP、高評判)はデータセンタープロキシの10倍のコストがかかるが、成功率はせいぜい2倍にしかならない。1時間に100 SKUを10地域で監視する価格監視運用では、月間プロキシ費用が2,000ドルを超える可能性がある。代替案である無料の公開プロキシの使用は、そのIPが主要なアンチボットサービスですでにフラグされているため、非現実的である。無料プロキシからの1回のリクエストでCAPTCHAまたは403応答が発生する。
実践的なワークフロー:レート制限、IPクールダウン、エラーハンドリング
スクレイパーはプロキシIPごとにステートマシンを実装する必要がある。成功したリクエストの後、プロキシはクールダウン期間に入る——ホテルサイトでは30秒、SaaS管理パネルでは60秒。失敗(HTTP 403、429、またはCAPTCHAページ)の後、クールダウンは5分に延長され、プロキシは再評価のためにフラグされる。トークンバケットレートリミッターを使用して、すべてのプロキシ全体で例えば1秒あたり2リクエストのグローバルキャップを適用する。以下のPythonスニペット(asyncioとaiohttpを使用)はコアループを示している:
import asyncio, aiohttp, random
PROXY_POOL = [{"url": "http://user:pass@fr1:3128", "cooldown_until": 0}]
async def fetch_price(session, proxy, url):
now = asyncio.get_event_loop().time()
if now < proxy["cooldown_until"]:
await asyncio.sleep(proxy["cooldown_until"] - now)
try:
async with session.get(url, proxy=proxy["url"],
headers={"Accept-Language": "fr-FR"}) as resp:
if resp.status == 200:
proxy["cooldown_until"] = now + 30
return await resp.text()
else:
proxy["cooldown_until"] = now + 300
return None
except Exception:
proxy["cooldown_until"] = now + 300
return None
同じプロキシからの連続失敗に対して指数バックオフを追加する——3回のエラー後、そのIPを24時間休止する。成功応答と総試行数の比率を監視し、ある地域で20%を下回った場合、その国のプロキシプール全体をローテーションする。最後に、すべての応答ヘッダー、特にSet-CookieとX-Frame-Optionsをログに記録する。これらは、サイトがJavaScript実行を必要とするボット検出スクリプトを実行しているかどうかを明らかにするためである。クライアントサイドレンダリングに依存するサイトでは、PlaywrightやPuppeteerのようなヘッドレスブラウザに切り替える必要があり、これによりレイテンシとプロキシコストが一桁増加する。地域間の価格監視は週末プロジェクトではなく、絶えず変化するターゲットに対して継続的な調整を必要とする継続的なエンジニアリング投資である。