Yelp は、ウェブ上で最大のクラウドソーシング レビュー プラットフォームの 200 つです。 30 か国以上のレストラン、バー、サロン、ショップ、その他のビジネスに関する XNUMX 億件を超えるレビューが含まれており、アナリスト、研究者、起業家などにとって宝の山のデータが含まれています。
しかし、Web スクレイピングを通じてこのデータを抽出することは可能でしょうか?絶対に!
この包括的な 3000 語以上のガイドでは、Python を使用して Yelp から巨大なデータセットを抽出できる Web スクレイパーを構築するために必要なすべてを共有します。
ここで取り上げる内容の簡単な概要は次のとおりです。
- Python Webスクレイピング環境のセットアップ
- 検索クエリに一致するすべてのビジネスを検索して抽出する
- ビジネスプロフィールページから名前、住所、電話番号などの重要な詳細をスクレイピング
- 評価、ユーザーの詳細など、ビジネスに関するすべてのレビューを抽出します。
- プロキシ、遅延、その他のトリックによるボット検出の回避
ストラップを締めて、スクレイピングを始めましょう!
Python Webスクレイピング環境のセットアップ
Yelp をスクレイピングする前に、必要な依存関係を備えた Python 環境をセットアップする必要があります。
インストールする必要がある主要なパッケージがいくつかあります。
つながり申請 – HTTPリクエストをYelpのサーバーに送信するため
美しいスープ – Yelp の HTML ページからデータを解析して抽出するため
スクラップ – (オプション) スクレーパーを構築するためのフレームワーク
これらをインストールする前に、仮想環境を作成することをお勧めします。
python -m venv scraping-env
source scraping-env/bin/activate
これで、パッケージをインストールできるようになります。
pip install requests beautifulsoup4 scrapy
依存関係については以上です。 Yelp のサーバーがリクエストが実際のブラウザから来ていると認識できるように、有効なヘッダーも必要です。
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
}
重要なのは説得力を設定することです User-Agent
ヘッダ。実際のトラフィックをさらに模倣するには、複数のブラウザ ユーザー エージェントをローテーションすることをお勧めします。
スクレイピングを開始する準備が整いました。
Yelp でビジネスを探す
最初の課題は、収集する Yelp ビジネス プロファイルの URL を見つけることです。 Yelp は、これをクエリできるパブリック API やサイトマップを提供していません。
したがって、検索機能をリバース エンジニアリングして、検索語または場所に一致する企業を見つける必要があります。
典型的な検索クエリを分析してみましょう。
https://www.yelp.com/search?find_desc=restaurants&find_loc=San+Francisco
これにより、検索条件に一致するページ分割されたビジネスのセットが返されます。各ページには 10 件のビジネス リストが含まれています。
一致するすべてのビジネスを抽出するには、次のことを行う必要があります。
- 最初のページを取得して合計ビジネス数を取得します
- すべてのページをインクリメントして反復処理します。
start
パラメーター
このページネーション ロジックを Python で実装する方法は次のとおりです。
import requests
from urllib.parse import urlencode
from bs4 import BeautifulSoup
search_url = "https://www.yelp.com/search?"
params = {
"find_desc": "restaurants",
"find_loc": "San Francisco"
}
search_url += urlencode(params)
print("Fetching first page")
first_page = requests.get(search_url, headers=headers)
soup = BeautifulSoup(first_page.content, "html.parser")
businesses = soup.select(".businessName")
total = int(soup.select_one(".pagination-results-window").text.split()[0].replace(‘,‘, ‘‘))
print(f"Found {total} businesses")
# Calculate pages needed to cover all businesses
num_pages = math.ceil(total / 10)
print(f"Scraping {num_pages} pages...")
for page in range(0, num_pages):
# Update start param
params["start"] = page * 10
page_url = search_url + "&" + urlencode(params)
# Fetch page
print(f"Page {page+1}/{num_pages}")
page = requests.get(page_url, headers=headers)
# Extract businesses
page_soup = BeautifulSoup(page.content, "html.parser")
businesses.extend(page_soup.select(".businessName"))
print(f"Found {len(businesses)} businesses!")
これを詳しく見てみましょう:
- まずはベースの検索 URL と検索パラメータから始めます
- 最初のページを取得して合計ビジネス数を取得します
- すべてのビジネスをカバーするために必要なページ数を計算する
- ページを繰り返し更新して、
start
パラメータ - 各ページでビジネスリストを抽出し、メインリストに追加します
私のテストでは、これは上に抽出されました サンフランシスコの 6,000 軒のレストランのリスト – 30 行の Python としては悪くありません。
いくつかの追加の調整を加えれば、これを都市全体または国全体の Yelp ビジネス スクレーパーに変えることができます。
ビジネスプロフィールページのスクレイピング
ビジネス プロファイルの URL を検出できるようになったので、次のステップでは、それぞれにアクセスして次のような重要な詳細を抽出します。
- 名前
- 住所
- 電話
- 営業時間
- 説明
- 写真
- そして、もっと...
Yelp のビジネス ページは動的にレンダリングされますが、基礎となる HTML は BeautifulSoup で解析できるほど単純です。
スニペットの例を見てみましょう。
<p>
<strong>Phone:</strong>
415-387-2147
</p>
<p>
<strong>Address:</strong>
1345 9th Ave, San Francisco, CA 94122
</p>
<!-- And so on... -->
いくつかの適切に配置された CSS セレクターを使用して、各ビットの情報を抽出できます。
from bs4 import BeautifulSoup
import requests
business_url = "https://www.yelp.com/biz/burma-superstar-san-francisco"
page = requests.get(business_url, headers=headers)
soup = BeautifulSoup(page.content, "html.parser")
name = soup.select_one("h1").text
phone = soup.find("strong", string="Phone:").next_sibling.strip()
address = soup.find("strong", string="Address:").next_sibling.strip()
hours = {}
for day in soup.select(".day-hours"):
day_name = day.select_one(".day-name").text
hours[day_name] = day.select_one(".hours").text
print(name)
print(phone)
print(address)
print(hours)
# Burma Superstar
# 415-387-2147
# 1345 9th Ave, San Francisco, CA 94122
# {‘Mon‘: ‘11:30am–3pm, 5–9:30pm‘, ‘Tue‘: ‘11:30am–3pm, 5–9:30pm‘...}
重要なポイントは次のとおりです。
-
select_one
名前、電話番号などの単数要素を抽出します。 - 時間などのネストされたデータの場合は、ループして辞書を構築します
- 一意性を高めるために、CSS セレクターにタグとクラスをプレフィックスします。
これらのスクレイピング構成要素を使用すると、各プロフィール ページから数十のフィールドを構造化された Python 辞書または JSON オブジェクトに抽出できます。
スクレイピングを検討するとよいその他のフィールドには次のようなものがあります。
- 「メキシコ」、「ブランチ」などのカテゴリタグ。
- 「ハンバーガー」、「寿司」、「コーヒー」などの料理タグ。
- 新型コロナウイルスの安全対策
- 価格帯
- 近所
- 緯度・経度
- そして、もっと...
ここで創造力を発揮すると、必要に応じて分析できる数百ものフィールドを含む広範な Yelp データセットを構築できます。
Yelp ビジネスページからのレビューのスクレイピング
レビューは Yelp のデータの最高の宝石です。これらは、消費者心理、トレンド、人口動態などに関する驚くべき洞察を提供します。
残念ながら、レビューは HTML に直接読み込まれません。これらは JavaScript 呼び出しを通じて動的に取得されます。
レビュー データを抽出するには、これらのリクエストを傍受して模倣する必要があります。
ビジネス ページを開いて、ブラウザ ツールでネットワーク リクエストを監視してみましょう。
ああ、レビューが次のような URL から読み込まれていることがわかります。
https://www.yelp.com/biz/{business_id}/reviews
場所 {business_id}
各ビジネスに固有のものです。ビジネスページのHTMLから抽出できます。
レビューは次の方法でページ分けされます。 start
パラメータ。したがって、同じページネーション戦略に従います。
- 最初のページを取得して総レビュー数を取得します
- すべてのページをインクリメントして反復処理します。
start
ビジネスのすべてのレビューを抽出するスクリプトは次のとおりです。
import json
import requests
business_id = "WavvLdfdP6g8aZTtbBQHTw" # Extract this from HTML
review_url = f"https://www.yelp.com/biz/{business_id}/review_feed?rl=en&q=&sort_by=relevance_desc"
print("Fetching first page")
first_page = requests.get(review_url, headers=headers)
data = json.loads(first_page.text)
total = data["pagination"]["totalResults"]
print(f"Found {total} reviews")
reviews = data["reviews"]
for page in range(total//20 + 1): # 20 reviews per page
print(f"Fetching page {page+1}/{math.ceil(total/20)}")
next_page = f"{review_url}&start={page*20}"
page_data = requests.get(next_page, headers=headers).json()
reviews.extend(page_data["reviews"])
print(f"Scraped {len(reviews)} reviews!")
ブーム!現在、次のようなデータを含むビジネスの完全なレビュー コーパスが手に入ります。
{
"id": "xAG4O7l-t1ubiIsO4cXMYg",
"rating": 5,
"user": {
"id": "rpOyqD_893cqmDAtJLbdog",
"profile_url": "https://www.yelp.com/user_details?userid=rpOyqD_893cqmDAtJLbdog",
"name": "Sarah K.",
"location": "Los Angeles, CA",
//...
},
"text": "This place is incredible! The sushi melts in your mouth and the...",
//...
}
このデータを分析すると、場所、人口統計、料理の種類などにわたる顧客心理に関する強力なシグナルを得ることができます。
ボットの検出を回避する
ビジネスとレビュー用のスクレイパーを構築したので、次はそれをすべてまとめます。
問題が 1 つあります。Yelp のサーバーに何千ものリクエストを送信し始めると、すぐにブロックされてしまいます。
Yelp は、次のような不正行為を防止するために、高度なボット検出システムを採用しています。
- 使用制限 – ページをリクエストできる速度を制限します
- CAPTCHA – ユーザーに人間であることを確認するよう要求します
- IP 禁止 – 不正な IP アドレスをブロックします
Yelp を大規模にスクレイピングする際にブロックを回避するためのヒントをいくつか紹介します。
プロキシの使用
住宅用 IP の大規模なプールを介してトラフィックをルーティングすることで、スクレイパーをマスクし、簡単な IP 禁止を回避できます。
Requests モジュールでプロキシを使用する方法は次のとおりです。
from proxy_list import proxies
# Rotate proxy per request
proxy = random.choice(proxies)
requests.get(url, headers=headers, proxies={"http": proxy, "https": proxy})
のプールを持つことをお勧めします 少なくとも10,000 安全のため、異なる IP 範囲のプロキシを使用します。
ランダムな遅延を追加する
リクエスト間にさまざまな遅延を追加すると、人間の有機的な動作を模倣するのに役立ちます。
from random import randint
# Add random delay between 2s and 6s
time.sleep(randint(2, 6))
平均を目指す 3-5秒 ページの間。それ以上速いと赤旗が上がります。
ヘッドレスブラウザを使用する
匿名性を高めるために、Selenium などのヘッドレス ブラウザを使用して JavaScript をレンダリングし、保護をバイパスできます。
セッションごとにブラウザのフィンガープリントとプロキシを必ず変更してください。
2Captcha で CAPTCHA を解決
CAPTCHA にヒットした場合、2Captcha のようなサービスは自動的に CAPTCHA を解決してスクレイピングを続行します。
ほとんどのサービスでは、解決された CAPTCHA 2 件あたり約 1000 ドルの料金がかかります。これは、大規模なスクレイパーを拡張する価値があります。
アカウントの制限を尊重する
アカウントステータスページに注目してください。スクレイピング レートが高すぎる場合、Yelp は一時的な使用制限を強制する場合があります。
リクエストのペースを調整し、使用量のしきい値に近づいていることを示すエラーが発生した場合はリクエストを中止します。
Yelp のスクレイピング: 次のステップ
そして、これは Yelp のビジネス リスティング、プロフィール、レビューをスクレイピングするための中心的なテクニックをカバーしています。
抽出できるデータにより、多くの可能性が開かれます。
- 人口統計全体にわたる消費者心理を分析する
- トレンドと新しい料理の種類を追跡する
- ビジネスの成功要因の予測モデルを構築する
- 独自の SEO と評判を最適化する
- 広範な市場調査を実施する
- 広告機会を特定する
Yelp のサービス利用規約に従い、リクエスト量を制限し、ユーザーの個人データの抽出を避けることを忘れないでください。
このガイドがお役に立てば幸いです。他にご質問がある場合はお気軽にお問い合わせください。
ハッピースクレイピング!