なぜAliExpressスクレイピングが難しいのか
ドロップシッピングの商品選定において、AliExpressのトレンド商品データは命綱です。しかし、実際にscrape AliExpressを試した開発者の多くは、CAPTCHA・レート制限・空レスポンスに直面して挫折します。アリババグループは自社プラットフォームを守るため、業界最高水準のアンチボットスタックを投入しています。
本記事では、HTMLパースの限界を示したうえで、モバイルAPIエンドポイントを活用したAliExpress product researchの実践手法を解説します。プロキシ選定・SKU処理・データ鮮度管理まで、プロダクトリサーチツール構築に必要な知見をすべて盛り込みました。
AliExpressのサイト構造を理解する
スクレイピング戦略を決める前に、取得対象となる4つの主要ページタイプを把握しましょう。
検索結果ページ
URLパターン:https://www.aliexpress.com/wholesale?SearchText=wireless+earbuds
- 1ページあたり最大60商品(モバイルAPIでは50件)
- ページネーションは最大100ページ(実質5,000商品)
- 各商品カード:タイトル・価格・注文数・評価・配送情報
- フィルタ:価格範囲・送料・評価・配送オプション
商品詳細ページ
URLパターン:https://www.aliexpress.com/item/1005006001234567.html
- SKUバリアント(色・サイズ・素材)の組み合わせテーブル
- 価格はSKUごとに変動 — デスクトップHTMLでは初期SKUのみ表示
- 在庫数は直接表示されず、「残りX個」の断片情報のみ
- 販売者情報・店舗評価・フォロワー数
ストアページ
URLパターン:https://www.aliexpress.com/store/912345678
- 全商品一覧(カテゴリ別・ソート順指定可)
- ストア評価・設立年・所在地
- キュレーションコレクション・セール情報
トレンド商品フィード
URL:https://www.aliexpress.com/globox/top-rated および /choicenew
- カテゴリ別の人気商品ランキング
- 週次・月次のトレンド変動を追跡可能
- Choice商品(AliExpress品質保証付き)の識別フラグ
API vs HTML:どちらをスクレイプすべきか
デスクトップHTMLのスクレイピングには明確な限界があります。
| 比較項目 | デスクトップHTML | モバイルAPI(JSON) |
|---|---|---|
| レスポンス形式 | HTML(パース必要) | 構造化JSON |
| SKU情報 | 初期SKUのみ | 全バリアント含む |
| 在庫データ | 断片的 | SKU別在庫数 |
| 配送料 | 国コード固定 | destinationパラメータで柔軟 |
| レート制限 | 厳格(IP/セッション) | やや緩和 |
| CAPTCHA発生率 | 高 | 低〜中 |
| レスポンスサイズ | 500KB〜2MB | 20KB〜80KB |
結論:商品データのAliExpress product researchではモバイルAPIが圧倒的に有利です。HTMLパースはストアページの補完的取得に限定し、メインデータパイプラインはAPIで構築すべきです。
アリババグループのアンチボットスタック
AliExpressはアリババグループのセキュリティインフラを利用しています。主な防御レイヤーは以下の通りです。
TLSフィンガープリンティング
Pythonのrequestsライブラリが送信するTLSハンドシェイクは、通常のブラウザと異なるフィンガープリントを持ちます。アリババのエッジノードはこれを検出し、403または空レスポンスを返します。対策:curl_cffiやtls-clientなど、ブラウザ相当のTLSフィンガープリントを偽装できるライブラリを使います。
デバイスフィンガープリンティング
aeapi.alicdn.comが配信するJavaScriptが、Canvas・WebGL・フォント列挙などでデバイスIDを生成。このIDはリクエストヘッダー(x-ae-device等)に含まれ、セッション一貫性の検証に使われます。
レート制限の閾値
- 同一IP:約80〜120リクエスト/5分でsoft ban(HTTP 429またはCAPTCHAチャレンジ)
- 同一セッション:約200リクエスト/時間でアカウントロックリスク
- 検索API:未認証だと約30リクエスト/分でブロック
CAPTCHA
アリババ独自のCAPTCHA(AliVerify)が動作。スライドパズル型が主流で、画像認識による自動突破は困難です。CAPTCHAが出たらセッションをリセットし、新しいIPに切り替える方が現実的です。
モバイルAPIエンドポイントの活用
AliExpressモバイルアプリが利用するAPIエンドポイントは、デスクトップHTMLよりはるかにリッチなJSONを返します。以下に主要なエンドポイントを示します。
商品検索API
GET https://api-sg.aliexpress.com/openapi/param2/3/portals.open/api.searchItems
?keywords=wireless+earbuds
&pageNo=1
&pageSize=50
&sort=SALE_PRICE_ASC
&shipFromCountry=CN
&shipToCountry=US
※上記は公式APIポータル経由のエンドポイントですが、アプリキーが必要です。より実践的なのは、モバイルWebが内部で呼ぶ非公開エンドポイントです。
モバイルWeb内部API(推奨)
# 商品詳細(モバイルWeb内部API)
GET https://m.aliexpress.com/api/products/{itemId}?_lang=en
# 検索結果(モバイルWeb内部API)
GET https://m.aliexpress.com/api/search?SearchText=wireless+earbuds&page=1
# ストア商品一覧
GET https://m.aliexpress.com/api/store/{storeId}/items?pageNo=1&pageSize=50
レスポンス例(商品詳細 — 一部省略):
{
"data": {
"itemId": 1005006001234567,
"title": "TWS Wireless Earbuds Bluetooth 5.3...",
"price": {"minPrice": 12.99, "maxPrice": 29.99, "currency": "USD"},
"skuList": [
{"skuId": "120000381", "price": 12.99, "stock": 847,
"attributes": [{"name": "Color", "value": "Black"}]},
{"skuId": "120000382", "price": 15.99, "stock": 423,
"attributes": [{"name": "Color", "value": "White"}]}
],
"tradeInfo": {"orders": 5280, "rating": 4.7},
"storeInfo": {"storeId": 912345678, "storeName": "TechZone Official",
"positiveRate": 97.3, "followers": 12840}
}
}
このJSONには、HTMLでは取得困難な全SKUの在庫数・店舗評価の詳細・注文数が含まれています。これこそがAliExpress product researchの核となるデータです。
Python実装:レジデンシャルプロキシでトレンド商品を発見
以下のスクリプトは、ProxyHatのレジデンシャルプロキシ経由でAliExpressモバイルAPIを呼び出し、トレンド商品データを取得する例です。
import requests
import time
import json
from datetime import datetime
# ProxyHatレジデンシャルプロキシ設定
PROXY_URL = "http://user-country-US:YOUR_PASSWORD@gate.proxyhat.com:8080"
proxies = {"http": PROXY_URL, "https": PROXY_URL}
# ブラウザ相当のヘッダー(モバイルWebを模倣)
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
),
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en-US,en;q=0.9",
"Referer": "https://m.aliexpress.com/",
"X-Requested-With": "com.alibaba.aliexpresshd",
}
SESSION = requests.Session()
SESSION.headers.update(HEADERS)
SESSION.proxies.update(proxies)
def search_products(keyword: str, page: int = 1) -> dict:
"""AliExpressモバイルAPIで商品検索"""
url = "https://m.aliexpress.com/api/search"
params = {
"SearchText": keyword,
"page": page,
"sort": "BEST_MATCH",
}
try:
resp = SESSION.get(url, params=params, timeout=15)
resp.raise_for_status()
return resp.json()
except requests.exceptions.HTTPError as e:
if resp.status_code == 429:
print(f" ⚠ レート制限検出 — 60秒待機")
time.sleep(60)
return search_products(keyword, page)
raise
def get_product_detail(item_id: int) -> dict:
"""商品詳細を取得(全SKU・在庫・店舗情報含む)"""
url = f"https://m.aliexpress.com/api/products/{item_id}"
params = {"_lang": "en"}
resp = SESSION.get(url, params=params, timeout=15)
resp.raise_for_status()
return resp.json()
def extract_trending_products(keyword: str, max_pages: int = 5) -> list:
"""注文数×評価でトレンド商品を抽出"""
products = []
for page in range(1, max_pages + 1):
print(f"🔍 検索中: '{keyword}' ページ {page}")
data = search_products(keyword, page)
items = data.get("data", {}).get("items", [])
if not items:
break
for item in items:
detail = get_product_detail(item["itemId"])
product = detail.get("data", {})
products.append({
"item_id": product["itemId"],
"title": product["title"],
"min_price": product["price"]["minPrice"],
"max_price": product["price"]["maxPrice"],
"orders": product.get("tradeInfo", {}).get("orders", 0),
"rating": product.get("tradeInfo", {}).get("rating", 0),
"sku_count": len(product.get("skuList", [])),
"total_stock": sum(
s.get("stock", 0) for s in product.get("skuList", [])
),
"store_name": product.get("storeInfo", {}).get("storeName", ""),
"store_positive_rate": product.get("storeInfo", {}).get("positiveRate", 0),
"scraped_at": datetime.utcnow().isoformat(),
})
time.sleep(2) # 礼儀的な間隔
return products
# 実行例
trending = extract_trending_products("wireless earbuds", max_pages=3)
print(json.dumps(trending[:2], indent=2, ensure_ascii=False))
このスクリプトのポイント:
- レジデンシャルプロキシでIPローテーション — データセンタープロキシではAliExpressのWAFに即座にブロックされます
- モバイルUser-AgentでAPIエンドポイントにアクセス — デスクトップUAでは403が返る場合があります
- 429検出時は60秒待機してリトライ — CAPTCHA回避のための安全マージン
- 各商品の詳細を個別取得 — SKU・在庫・店舗評価を含む完全データ
より大規模な運用では、プロキシローテーション戦略を参照して、リクエストごとにIPを切り替える設定を検討してください。
SKUバリアント・配送料・販売者評価の処理
変動SKUのパース
AliExpressの商品は、色・サイズ・素材などのバリアントごとに独立したSKU IDを持ちます。APIレスポンスのskuListには各SKUの価格・在庫・属性が含まれますが、いくつか注意点があります。
- 価格階層:1SKUあたり最大36のバリアント組み合わせが存在。価格差は2倍以上になることも。
- 在庫の0表示:
stock: 0は「在庫切れ」ではなく「在庫数非公開」の可能性あり。注文数との相対比較で判断。 - 属性マッピング:SKUの
attributes配列は順不同。色×サイズの組み合わせを再構築するには、skuIdをキーにして属性を結合します。
def parse_sku_matrix(product_data: dict) -> list[dict]:
"""SKUバリアントを属性組み合わせ付きでパース"""
sku_list = product_data.get("skuList", [])
parsed = []
for sku in sku_list:
attrs = {a["name"]: a["value"] for a in sku.get("attributes", [])}
parsed.append({
"sku_id": sku["skuId"],
"price_usd": sku["price"],
"stock": sku.get("stock", None),
"is_available": sku.get("stock", 0) > 0,
**attrs, # Color=Black, Size=M などが展開される
})
return parsed
配送料の推定
配送料は宛先国・SKU・配送方式の組み合わせで変動します。モバイルAPIではshipToCountryパラメータで宛先を指定可能です。
# 配送料を含む商品詳細取得
def get_shipping_cost(item_id: int, sku_id: str, dest_country: str = "US") -> dict:
url = f"https://m.aliexpress.com/api/products/{item_id}/shipping"
params = {
"skuId": sku_id,
"country": dest_country,
"quantity": 1,
}
resp = SESSION.get(url, params=params, timeout=15)
resp.raise_for_status()
data = resp.json()
shipping_options = []
for option in data.get("data", {}).get("shippingOptions", []):
shipping_options.append({
"method": option["serviceName"],
"cost": option["freightAmount"]["value"],
"currency": option["freightAmount"]["currency"],
"estimated_days": option.get("estimateDeliveryTime", None),
})
return shipping_options
ドロップシッパーにとって重要なのは無料配送の有無と、ePacket/AliExpress Standard Shippingの到着日数です。これらは利益率に直結します。
販売者評価の解釈
ストア評価は以下の指標を総合的に判断します。
- positiveRate:97%以上が目安。95%未満は品質リスク。
- followers:フォロワー数は販売実績の代理指標。
- 設立年:3年以上のストアは安定性が高い。
- Choice認証:AliExpress Choiceバッジは品質・配送の保証付き。
データ鮮度とスクレイピング頻度
AliExpressのデータはどの程度の頻度で変わるのか。これを理解しないと、無駄なリクエストを繰り返すことになります。
価格変動の頻度
- セール期間:11.11・ブラックフライデー等のイベント前後は1時間ごとに価格が変わる
- 通常期:週1〜2回の価格改定が一般的
- クーポン適用:ストアクーポンは在庫状況に連動して自動付与される場合がある
在庫変動の頻度
- 人気商品:1時間で数百単位の在庫変動
- 通常商品:日次での補充が多い
- 季節商品:シーズンオフに在庫ゼロになるSKUが頻出
推奨スクレイピング頻度
| データ種別 | 推奨頻度 | 理由 |
|---|---|---|
| 価格監視 | 6〜12時間 | 1時間ごとは過剰。セール期間のみ1時間に短縮 |
| 在庫確認 | 12〜24時間 | 在庫切れの検知が目的なら半日で十分 |
| トレンド発掘 | 週1回 | 注文数の週次推移が見たい |
| 新商品検知 | 日次 | カテゴリの新着フィードを毎日チェック |
| 配送料 | 週1回 | キャンペーン以外はほぼ不変 |
過剰なスクレイピングはIPブロックのリスクを高めるだけでなく、取得データの質を下げません。適切な間隔を守り、AliExpress proxyとしてレジデンシャルプロキシを活用することが長期運用の鍵です。
プロキシ選定:なぜレジデンシャルが必須なのか
AliExpressのアンチボットシステムは、IPのASN(自律システム番号)をチェックしています。データセンタープロキシのIPは、DigitalOcean・AWS・HetznerなどのASNに属するため、即座にフィンガープリントされます。
| プロキシ種別 | AliExpressでの成功率 | 推奨用途 |
|---|---|---|
| データセンター | 10〜30% | テスト・低頻度の軽量リクエストのみ |
| レジデンシャル(回転) | 85〜95% | 検索API・商品詳細のメインパイプライン |
| モバイル | 90〜98% | 最も信頼性が高いがコストも高い |
ProxyHatのレジデンシャルプロキシは、195以上のロケーションからIPを選択可能です。国ターゲティングを使えば、特定の市場向け価格・配送料を正確に取得できます。
# 国別価格比較のためのプロキシ設定例
# 日本からの価格を取得
JP_PROXY = "http://user-country-JP:PASSWORD@gate.proxyhat.com:8080"
# ドイツからの価格を取得
DE_PROXY = "http://user-country-DE:PASSWORD@gate.proxyhat.com:8080"
# アメリカからの価格を取得(都市指定も可能)
US_PROXY = "http://user-country-US-city-newyork:PASSWORD@gate.proxyhat.com:8080"
def compare_regional_prices(item_id: int, countries: list[str]) -> dict:
"""複数国の価格・送料を比較"""
results = {}
for country in countries:
proxy = f"http://user-country-{country}:PASSWORD@gate.proxyhat.com:8080"
session = requests.Session()
session.proxies = {"http": proxy, "https": proxy}
session.headers.update(HEADERS)
detail = session.get(
f"https://m.aliexpress.com/api/products/{item_id}",
params={"_lang": "en"},
timeout=15,
).json()
results[country] = {
"price": detail["data"]["price"]["minPrice"],
"currency": detail["data"]["price"]["currency"],
}
time.sleep(3)
return results
地域別価格差は、ドロップシッパーにとって利益機会の発見に直結します。詳しくはSERP追跡ユースケースも参照してください。
スケール時のベストプラクティス
リクエスト間隔の設計
- 同一IPでのリクエスト間隔:3〜5秒を最低ラインに
- セッションあたり:200リクエスト/時間を上限に
- IPローテーション時は新しいIPで初回リクエストを検索ページに — いきなり商品詳細だと不自然
エラーハンドリング
- HTTP 429:レート制限。IPをローテーションして60秒後にリトライ。
- HTTP 403:IPブロックまたはTLSフィンガープリント検出。IPを変えて再試行。
- CAPTCHAレスポンス:セッションを破棄し、新しいIP+セッションで再開。
- 空JSON:IPがgeoブロックされている可能性。国ターゲティングを確認。
データパイプラインの構成
- 検索APIでキーワードごとの商品リストを取得(1時間ごと or オンデマンド)
- 各商品IDをキューに投入
- ワーカーが商品詳細APIを呼び出し(レジデンシャルプロキシ経由)
- SKU・在庫・配送データを正規化してデータベースに保存
- 価格変動検知 → アラート or 自動仕入れ判断
Key Takeaways(重要ポイント)
- モバイルAPIを優先:デスクトップHTMLのパースは避け、
m.aliexpress.com/api/エンドポイントを使う。JSONで全SKU・在庫・店舗情報が取得できる。- レジデンシャルプロキシが必須:データセンタープロキシではAliExpressのWAFを通過できない。ProxyHatのレジデンシャルプロキシでIPローテーションを。
- SKUごとに価格・在庫が違う:商品の「価格」だけでなくSKUマトリクス全体を取得し、利益計算に使う。
- スクレイピング頻度は目的に合わせる:価格監視は6〜12時間、トレンド発掘は週1回。過剰リクエストはリスクを増すだけ。
- 国ターゲティングで地域差を捕捉:プロキシのgeo機能を使い、ターゲット市場の価格・送料を正確に取得。
まとめ:次のステップ
AliExpressのスクレイピングは、モバイルAPIとレジデンシャルプロキシの組み合わせで安定運用が可能です。まずは単一キーワードの検索→詳細取得パイプラインを構築し、そこからSKU処理・配送料推定・価格変動アラートへと拡張してください。
プロキシの準備がまだなら、ProxyHatのプランから始めましょう。レジデンシャル・モバイル・データセンタープロキシを柔軟に組み合わせて、AliExpress product researchのデータパイプラインを構築できます。
Webスクレイピング全般のノウハウは、Webスクレイピングユースケースページも参考にしてください。






