Yelpのビジネスリスティングとレビューのスクレイピング:2026年の実践ガイド
法的注意事項:本記事は公開データへのアクセスのみを対象としています。Yelpの利用規約を遵守し、米国ではComputer Fraud and Abuse Act(CFAA)、EUではGDPRに準拠してください。ログインが必要なコンテンツのスクレイピングは推奨しません。
Yelpのビジネスリスティングとレビューのスクレイピングは、ローカルビジネスデータセットを構築する開発者にとって重要な技術です。2026年現在、YelpはPerimeterX(現HUMAN)による強力なボット検知システムを運用しており、データセンタープロキシからのリクエストはわずか5〜10回でブロックされるのが一般的です。本ガイドでは、公開データへの合法的なアクセス方法、PerimeterXの仕組み、回転住宅プロキシを用いた実践的なスクレイピング手法を解説します。
公開データとFusion APIの制限
Yelpには公式のFusion APIが用意されていますが、無料プランでは各ビジネスにつき3件のレビューしか取得できません。一方、Webページ上では以下のデータがログインなしで公開されています:
- ビジネス名、住所、電話番号(
/biz/<slug>ページ) - 評価(星の数)とレビュー総数
- カテゴリ、営業時間、価格帯
- レビュー本文、投稿者名、投稿日付、役に立った数
- 写真のURL
Fusion APIの詳細についてはYelp Fusion API公式ドキュメントを参照してください。APIが要件を満たす場合は、スクレイピングよりもAPIの使用を優先すべきです。
Fusion API vs スクレイピングの比較
| 項目 | Fusion API | Webスクレイピング |
|---|---|---|
| レビュー取得数 | 最大3件/ビジネス | 全レビュー(ページネーション) |
| 認証 | APIキー必須 | 不要(公開ページ) |
| レート制限 | 5000リクエスト/日 | プロキシで拡張可能 |
| データの鮮度 | API応答依存 | リアルタイム |
| 利用規約リスク | 低(公式) | 中(ToS確認必須) |
Yelpのアンチボット防御:PerimeterX/HUMAN
YelpはPerimeterX(現在はHUMAN Securityが提供)を利用してボットトラフィックを検知しています。主な防御メカニズムは以下の通りです:
_px3 Cookieとセンサーチャレンジ
PerimeterXは_px3というCookieを発行し、ブラウザの「センサーデータ」(マウス動作、キーボード入力タイミング、デバイス指纹など)を収集します。このデータが人間らしいパターンと一致しない場合、CAPTCHAページにリダイレクトされます。
TLS指纹
PerimeterXはTLSハンドシェイクの指纹も検査します。Pythonのrequestsライブラリが使用するTLSスタックは、ChromeやFirefoxのそれと異なるため、ボットとして検知される可能性があります。ProxyHatドキュメントで推奨されているTLS指纹の偽装手法を検討してください。
IPレピュテーションスコアリング
データセンターIP(AWS、GCP、Azureなど)からのリクエストは、IPレピュテーションが低いため即座にフラグ付けされます。住宅プロキシを使用することで、実際のISPに割り当てられたIPアドレスからのアクセスとして扱われます。
なぜ回転住宅プロキシが必要なのか
Yelpのスクレイピングに住宅プロキシが必須な理由は3つあります:
- IPレピュテーション:データセンターIPはPerimeterXによって即座にブロックされます。住宅IPは実際のISPに登録されているため、検知リスクが大幅に低下します。
- 地理的ターゲティング:Yelpの検索結果は位置に依存します。
-country-US-city-austinのようなジオターゲティングフラグを使用することで、オースティン周辺のローカルビジネス結果を取得できます。 - 回転によるレート制限回避:リクエストごとにIPを回転させることで、単一IPあたりのリクエスト数を低く保ち、レート制限トリガーを回避できます。
ProxyHatの住宅プロキシは99.9%の稼働率と100の同時セッションをサポートしており、Yelpスクレイピングに適しています。ProxyHatの料金プランと利用可能なロケーションを確認してください。
実装例:PythonでYelpビジネスページをスクレイピング
以下の例では、ProxyHatの住宅プロキシを使用してYelpビジネスページにアクセスし、埋め込まれた__INITIAL_STATE__JSONブロブからビジネスデータとレビューを抽出します。
import requests
import json
import re
import time
import random
# ProxyHat residential proxy with US geo-targeting
# ジオターゲティングとスティッキーセッションを設定
proxy_url = (
"http://user-country-US-city-austin-session-yelp01:"
"PASSWORD@gate.proxyhat.com:8080"
)
proxies = {
"http": proxy_url,
"https": proxy_url,
}
# Rotating User-Agents to lower fingerprint risk
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
]
headers = {
"User-Agent": random.choice(user_agents),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Referer": "https://www.yelp.com/",
}
def scrape_yelp_biz(biz_slug, max_retries=3):
url = f"https://www.yelp.com/biz/{biz_slug}"
for attempt in range(max_retries):
try:
response = requests.get(
url, proxies=proxies, headers=headers, timeout=30
)
if response.status_code == 200:
# Extract __INITIAL_STATE__ blob
match = re.search(
r'__INITIAL_STATE__\s*=\s*({.*?});',
response.text,
re.DOTALL
)
if match:
state = json.loads(match.group(1))
biz = state.get(
"bizDetailsPageProps", {}
).get("bizResponse", {})
# Parse truncated review object
reviews = biz.get("reviews", [])[:3]
result = {
"name": biz.get("name", ""),
"rating": biz.get("rating", 0),
"review_count": biz.get("reviewCount", 0),
"categories": [
c.get("title", "")
for c in biz.get("categories", [])
],
"reviews": [
{
"text": r.get("comment", {}).get("text", "")[:200],
"rating": r.get("rating", 0),
"author": r.get("author", {}).get("name", ""),
}
for r in reviews
],
}
return result
elif response.status_code == 403:
print(f"Blocked (403), retrying... attempt {attempt + 1}")
time.sleep(random.uniform(5, 15))
else:
print(f"Status {response.status_code}")
time.sleep(2)
except Exception as e:
print(f"Error: {e}")
time.sleep(5)
return None
# Example usage
result = scrape_yelp_biz("some-business-austin")
if result:
print(json.dumps(result, indent=2, ensure_ascii=False))
このコードは__INITIAL_STATE__からビジネス名、評価、レビュー総数、カテゴリ、および最初の3件のレビュー(テキストは200文字で切り詰め)を抽出します。スティッキーセッション(-session-yelp01)を使用することで、ページネーション時のIP一貫性を保ちます。
実装例:Node.jsでSOCKS5プロキシを使用
Node.js環境では、SOCKS5プロキシ(ポート1080)を使用してYelpにアクセスできます。
const { SocksProxyAgent } = require('socks-proxy-agent');
const fetch = require('node-fetch');
// ProxyHat SOCKS5 proxy with US geo-targeting
const agent = new SocksProxyAgent(
'socks5://user-country-US-city-austin-session-yelp02:' +
'PASSWORD@gate.proxyhat.com:1080'
);
async function scrapeYelpBusiness(slug) {
const url = `https://www.yelp.com/biz/${slug}`;
const response = await fetch(url, {
agent,
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) ' +
'Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml',
'Accept-Language': 'en-US,en;q=0.9',
'Referer': 'https://www.yelp.com/',
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const html = await response.text();
const match = html.match(/__INITIAL_STATE__\s*=\s*({.*?});/s);
if (match) {
const state = JSON.parse(match[1]);
const biz = state?.bizDetailsPageProps?.bizResponse || {};
const reviews = (biz.reviews || []).slice(0, 3);
return {
name: biz.name || '',
rating: biz.rating || 0,
reviewCount: biz.reviewCount || 0,
reviews: reviews.map(r => ({
text: (r.comment?.text || '').slice(0, 200),
rating: r.rating || 0,
author: r.author?.name || '',
})),
};
}
return null;
}
// Example
scrapeYelpBusiness('some-business-austin')
.then(data => console.log(JSON.stringify(data, null, 2)))
.catch(err => console.error(err));
ページネーションとレート制限のペーシング
Yelpのレビューはページごとに表示され、URLパラメータstart=20、start=40などでページネーションできます。ただし、同じIPから短時間に多数のページをリクエストするとPerimeterXがトリガーされます。
推奨されるペーシング戦略
- リクエスト間隔:各リクエストの間に3〜8秒のランダムな遅延を挿入します。一定間隔ではなくランダム化が重要です。
- セッション切り替え:10〜20リクエストごとにスティッキーセッションIDを変更し、新しいIPに切り替えます。
- ジオターゲティングの維持:セッションを切り替えても
-country-USフラグは維持し、一貫した地理的コンテキストを保ちます。 - User-Agentの回転:5〜10リクエストごとにUser-Agentを切り替え、ブラウザ指纹の多様性を確保します。
# Pagination with rate-limit pacing
import time
import random
def scrape_all_reviews(biz_slug, max_pages=10):
all_reviews = []
session_counter = 0
for page in range(max_pages):
start = page * 20
session_id = f"yelp-page-{page // 5}"
proxy_url = (
f"http://user-country-US-city-austin-"
f"session-{session_id}:"
f"PASSWORD@gate.proxyhat.com:8080"
)
url = f"https://www.yelp.com/biz/{biz_slug}?start={start}"
# ... fetch and parse ...
# Random delay between 3-8 seconds
delay = random.uniform(3, 8)
time.sleep(delay)
session_counter += 1
# Rotate session every 5 pages
if session_counter >= 5:
session_counter = 0
return all_reviews
よくある失敗とエッジケース
1. CAPTCHAループ
データセンターIPを使用すると、最初のリクエストでCAPTCHAページにリダイレクトされることがあります。これは_px3Cookieが発行されていないことを意味します。解決策は住宅プロキシに切り替えることです。
2. レビューの動的読み込み
Yelpは一部のレビューをJavaScriptで動的に読み込みます。__INITIAL_STATE__には最初の数件のレビューのみ含まれ、追加のレビューは/review_feedエンドポイントから取得する必要があります。
3. スティッキーセッションの切り替えタイミング
同じセッションIDを長期間使用すると、そのIPがPerimeterXにフラグ付けされる可能性があります。10〜20リクエストごとにセッションを切り替えることを推奨します。
4. robots.txtの確認
スクレイピングを開始する前に、必ずYelpのrobots.txtを確認し、クロールが許可されているパスかどうかを検証してください。
倫理的スクレイピングと公式APIの優先
スクレイピングは強力なツールですが、責任を持って使用する必要があります。以下のガイドラインに従ってください:
- 公式APIを優先:Fusion APIが要件を満たす場合は、スクレイピングではなくAPIを使用してください。APIは安定しており、ToSに準拠しています。
- 個人情報の取り扱い:レビュー投稿者の名前や写真は個人データに該当する可能性があります。GDPR下では、個人データの処理には法的根拠が必要です。
- ログイン壁のコンテンツ:ログインが必要なコンテンツ(友達のレビューやプライベートメッセージなど)のスクレイピングは避けてください。
- サーバーへの配慮:適切なレート制限を設定し、Yelpのサーバーに過度な負荷をかけないようにしてください。
- データの利用目的:取得したデータをYelpの競合サービスの構築に使用しないでください。これは多くのプラットフォームのToSで明示的に禁止されています。
ウェブスクレイピングのベストプラクティスについては、ProxyHatのウェブスクレイピングユースケースも参照してください。SERP追跡についての詳細はSERPトラッキングページをご覧ください。
Key Takeaways
- Yelpの公開ページにはビジネスプロファイル、評価、レビュー本文がログインなしでアクセス可能。Fusion APIは3件のレビューに制限。
- PerimeterX/HUMANは_px3 Cookie、TLS指纹、IPレピュテーションでボットを検知。データセンターIPは5〜10回でブロック。
- 回転住宅プロキシ(USジオターゲティング付き)がYelpスクレイピングに必須。ProxyHatはgate.proxyhat.com:8080(HTTP)または:1080(SOCKS5)で接続。
- ページネーション時は3〜8秒のランダム遅延、5ページごとのセッション切り替え、User-Agent回転で指纹リスクを低減。
- 倫理的スクレイピングを徹底:robots.txtを確認、個人情報を尊重、公式APIを優先。
ProxyHatの住宅プロキシを使えば、Yelpの公開データに安定してアクセスできます。料金プランを確認し、ProxyHatドキュメントで詳細な設定方法を参照してください。






