2026年にPythonでGoogle Mapsレビューをスクレイピングする方法 — 完全ガイド

PlaywrightとSeleniumを使い、PythonでGoogle Mapsレビューをスクレイピングする方法を解説します。アンチボット対策の回避方法やノーコードの代替手段もご紹介します。

Livescraper TeamApr 6, 2026
2026年にPythonでGoogle Mapsレビューをスクレイピングする方法 — 完全ガイド

Google Mapsからレビューを手作業でコピー&ペーストしようとしたことがある方なら、その大変さをご存じでしょう。ビジネスをクリックし、レビューをスクロールし、一件一件コピーする……これを50件のビジネスに対して行うと、午後がまるごと潰れてしまいます。私自身、それを経験してきました。

だからこそ、PythonでGoogle Mapsレビューをスクレイピングすることに大きな意味があるのです。コードを一度書いてしまえば、面倒な作業をすべて自動でこなしてくれます。レビュアーの名前、星評価、レビュー本文、日付など、あらゆる情報を取得できます。自社ブランドの評判を追跡している方も、競合の動向を見張っている方も、何かしらの調査プロジェクト用にデータセットを構築している方も、自動化こそが正解です。

本ガイドでは、2通りの方法を順を追って解説します。1つはPlaywrightを使う方法、もう1つはSeleniumを使う方法です。どちらでも動きます。さらに、Googleのアンチボットシステムをかいくぐる方法もお見せします(そう、彼らは確実にあなたをブロックしようとしてきます)。そして、コードをまるごとスキップしたい方のために、すべてをまとめて処理してくれるノーコードツールもご紹介します。

本記事を読み進めるのにPythonの達人である必要はありません。ライブラリをインストールしてスクリプトを実行できるなら、それで十分です。

Google Mapsレビューとは何か、なぜスクレイピングするのか?

Google Mapsレビューが何かは、すでにご存じでしょう。ビジネスに対して人々が残す星評価とコメントのことです。Google Maps上のあらゆるピザ屋、歯科医院、ホテル、配管業者にもレビューが存在します。意外と気づかれていないのは、それらのレビューに眠っている有用なデータの量です。

どんなデータが抽出できるのか?

各レビューから取得できる情報は次のとおりです。

  • レビュアー名 — 投稿者
  • 星評価 — 1〜5の星スコア
  • レビュー本文 — 投稿された実際のコメント
  • レビュー投稿日 — 投稿された日時
  • オーナーからの返信 — ビジネスが返信していれば、それも取得可能
  • レビュアープロフィールへのリンク — 投稿者のGoogleプロフィールURL
  • レビュー写真 — 添付された画像があれば取得可能

では、このデータを実際に何に使うのか?

実はかなり多くの用途があります。

  • ブランドモニタリング — 複数の拠点における自社ビジネスへの声を継続的に把握する
  • 競合調査 — レビューを基に、競合がどこで失敗している(あるいは成功している)かを把握する
  • 感情分析 — レビューをNLPツールに通して、顧客の感じ方のパターンを発見する
  • リードジェネレーション — 評判の悪いビジネスを見つけ、自社の製品やサービスを売り込む
  • 市場調査 — 業界全体のレビュートレンドを観察する
  • 学術研究 — 消費者行動に関する研究用データセットを構築する

Googleの公式APIとWebスクレイピング — 何が違うのか?

コードに入る前に、知っておくべきことがあります。Googleにはこの用途向けの公式APIがあります — Places APIです — しかし正直なところ、ほとんどの人が求めることに対しては機能がかなり限定的です。

Google Places API(公式の方法)

APIの実態はこうです。

  • 取得できるのは1ビジネスあたり5件のレビューだけです。5件。それが上限です。
  • 有料です — Place Detailsの場合、1,000リクエストあたりおよそ$17かかります
  • レビューの全履歴はまったく取得できません
  • 表示される5件はGoogleが選びます(彼らのアルゴリズムが決めるのであって、あなたではありません)
  • 明るい面としては、データはきれいなJSONで返ってくるので、パースは簡単です

Webスクレイピング(これから行うこと)

一方、スクレイピングなら以下のとおりです。

  • そのビジネスにあるすべてのレビューを取得できます — 5件だけではありません
  • 無料です(まあ、あなたの時間は無料ではありませんが、ツール自体は無料です)
  • 実際の日付付きで、完全なレビュー履歴を取得できます
  • セットアップに手間がかかるのは間違いありません
  • そしてGoogleがページレイアウトを変えるたびに、コードを更新する必要があります

つまり、5件で十分ならAPIを使えばいいですが、もし全体像 — 数百件あるいは数千件のレビュー — が必要なら、自分でスクレイピングするか、それを代わりに行ってくれるLivescraperのようなツールを利用する必要があります。

前提条件 — 始める前に必要なもの

まずはお使いのマシンをセットアップしましょう。難しい作業はありませんが、いくつかインストールしておくものがあります。

1. Python 3.9以上

ターミナル(Windowsならコマンドプロンプト)を開いて、バージョンを確認してください。

python --version
# Python 3.9以上が必要です。2026年なら3.12または3.13が理想です。

まだPythonがインストールされていませんか? python.orgから入手してください。Macならbrew install pythonでも動きます。

2. 仮想環境を作成する

これにより、プロジェクトの依存関係をシステムの他の環境から切り離せます。後々のトラブルを避けるためにも、強くおすすめします。

# プロジェクトフォルダを作って移動
mkdir google-reviews-scraper
cd google-reviews-scraper

# 仮想環境を作成
python -m venv venv

# 有効化
# Mac/Linux:
source venv/bin/activate
# Windows:
venv\\Scripts\\activate

3. ライブラリのインストール

以下では2通りの方法を解説します。使う予定の方をインストールしてください(両方試したいなら両方でも構いません)。

# Playwright用(個人的にはこちらがおすすめ)
pip install playwright pandas
playwright install chromium

# Selenium用
pip install selenium webdriver-manager pandas beautifulsoup4

各ライブラリが何をするものか、今すぐ理解しなくても大丈夫です — 進めながら解説します。

方法1:Playwrightでレビューをスクレイピングする(推奨)

PlaywrightはMicrosoftが開発したブラウザ自動化ツールです。私はこの種の作業ではSeleniumよりPlaywrightを好みます。動的なページの扱いが上手く、速度も速く、書くべき定型コードが少なくて済むからです。Seleniumの数年後に登場したこともあり、その分多くの不便な部分が改善されています。

なぜSeleniumではなくPlaywrightなのか?

要点をまとめるとこうです。

  • 自動的に待ってくれます。Playwrightは要素の準備が整ってからクリックするタイミングを把握しています。Seleniumでは、あちこちにtime.sleep()をばら撒いてうまくいくのを祈ることになります。
  • 純粋に高速です。内部でのブラウザとの通信方式がより効率的です。
  • セレクタがより柔軟です。CSS、XPath、テキストマッチ、ARIAロール — すべて標準で対応しています。
  • ステルス化が容易です。サイトに即座にボットだと判定されないよう設定するのが簡単です。
  • 複数ブラウザに対応しています。Chromium、Firefox、WebKit(Safariのエンジン)すべてに対応しています。

ステップ1:基本的なセットアップ

では、コードを書いていきましょう。scraper.pyというファイルを作って、ブラウザのセットアップから始めます。

from playwright.sync_api import sync_playwright
import pandas as pd
import time
import random
import re

def create_browser():
    """Launch a browser that looks like a real user."""
    p = sync_playwright().start()
    browser = p.chromium.launch(
        headless=False,  # Set True for production
        args=[
            '--disable-blink-features=AutomationControlled',
            '--no-sandbox',
        ]
    )
    context = browser.new_context(
        viewport={'width': 1366, 'height': 768},
        user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                   'AppleWebKit/537.36 (KHTML, like Gecko) '
                   'Chrome/124.0.0.0 Safari/537.36',
        locale='en-US',
    )
    return p, browser, context

ここで何が起きているかを解説します。私たちは、スクリプトではなく普通の人間がブラウジングしているように見える設定でChromiumブラウザを起動しています。headless=Falseの部分は、実際にブラウザウィンドウが画面に表示されることを意味しています。これは、何が起きているかを目で確認できるためデバッグに非常に便利です。ユーザーエージェント文字列は、私たちが使っているとされるブラウザをGoogleに伝えるためのものです。そしてdisable-blink-featuresフラグは、「このブラウザは自動化ソフトに操作されています」という分かりやすいサインを取り除いてくれます。

ステップ2:ビジネスへ移動してレビュータブを開く

次に、実際にGoogle Mapsのビジネスページに移動し、レビューセクションをクリックする必要があります。この部分はシンプルです。

def open_reviews_panel(page, place_url):
    """Navigate to a Google Maps place and open the reviews tab."""
    page.goto(place_url, wait_until='networkidle')

    # Accept cookies if prompted
    try:
        page.click('button:has-text("Accept all")', timeout=3000)
    except:
        pass

    # Wait for the page to fully load
    page.wait_for_selector('button[data-tab-index="1"]', timeout=10000)

    # Click on the "Reviews" tab
    page.click('button[data-tab-index="1"]')
    time.sleep(2)  # Let reviews load

    print("Reviews panel opened successfully")

かなりシンプルですよね。URLにアクセスし、ページが完全に読み込まれるのを待ち、あの煩わしいCookie同意ポップアップに対応し(ヨーロッパにいる方なら何の話か分かるでしょう)、それから「Reviews」タブをクリックします。data-tab-index="1"のセレクタはレビュータブを指しています — 少なくとも2026年初頭時点では。Googleがレイアウトを変えれば、このセレクタも更新が必要になるかもしれません。

ステップ3:スクロールしてさらにレビューを読み込む

ここからが面白いところです。Google Mapsは一度にすべてのレビューを読み込みません — 最初は10件ほど表示し、スクロールするにつれて追加で読み込まれます。そのため、必要な分(あるいは目標件数)に達するまで、スクロールしては待つ、を繰り返す必要があります。

def scroll_reviews(page, max_reviews=100):
    """Scroll the reviews panel to load more reviews."""
    scrollable = page.query_selector('div.m6QErb.DxyBCb.kA9KIf.dS8AEf')
    if not scrollable:
        print("Could not find scrollable reviews container")
        return

    last_count = 0
    scroll_attempts = 0
    max_attempts = 50

    while scroll_attempts < max_attempts:
        # Scroll down inside the reviews panel
        scrollable.evaluate('el => el.scrollTop = el.scrollHeight')

        # Wait for new reviews to load
        time.sleep(random.uniform(1.5, 3.0))

        # Count current reviews
        reviews = page.query_selector_all('div.jftiEf.fontBodyMedium')
        current_count = len(reviews)

        print(f"Loaded {current_count} reviews...")

        # Stop if we've reached our target
        if current_count >= max_reviews:
            print(f"Reached target of {max_reviews} reviews")
            break

        # Stop if no new reviews loaded (we've reached the end)
        if current_count == last_count:
            scroll_attempts += 1
            if scroll_attempts >= 3:
                print(f"No more reviews to load. Total: {current_count}")
                break
        else:
            scroll_attempts = 0

        last_count = current_count

ここで難しいのは、正しいスクロール可能コンテナを見つけることです — スクロールするのはメインのページではなく、レビューパネル内の特定のdivです。これをJavaScriptで一番下までスクロールし、その後ランダムな時間(1.5〜3秒)だけ待機して、より人間らしく見せます。スクリプトは、目標件数のレビューに達するか、何度か試行しても新しいレビューが表示されなくなるまで続きます。

ステップ4:レビューデータを抜き出す

ページ上にすべてのレビューが読み込まれたら、実際にそれぞれからデータを取得していきます。次の関数では、すべてのレビュー要素をループし、名前、評価、本文、日付、そしてオーナーからの返信を取り出します。

def extract_reviews(page):
    """Extract all review data from the loaded reviews."""
    reviews_data = []
    review_elements = page.query_selector_all('div.jftiEf.fontBodyMedium')

    for element in review_elements:
        try:
            # Reviewer name
            name_el = element.query_selector('.d4r55')
            name = name_el.inner_text() if name_el else 'Anonymous'

            # Star rating
            rating_el = element.query_selector('.kvMYJc')
            rating = 0
            if rating_el:
                aria = rating_el.get_attribute('aria-label')
                match = re.search(r'(\\d+)', aria or '')
                rating = int(match.group(1)) if match else 0

            # Review text (click "More" to expand if needed)
            more_btn = element.query_selector('button.w8nwRe.kyuRq')
            if more_btn:
                try:
                    more_btn.click()
                    time.sleep(0.3)
                except:
                    pass

            text_el = element.query_selector('.wiI7pd')
            text = text_el.inner_text() if text_el else ''

            # Review date
            date_el = element.query_selector('.rsqaWe')
            date = date_el.inner_text() if date_el else ''

            # Owner response
            response_el = element.query_selector('.CDe7pd')
            owner_response = response_el.inner_text() if response_el else ''

            reviews_data.append({
                'reviewer_name': name,
                'rating': rating,
                'review_text': text,
                'review_date': date,
                'owner_response': owner_response,
            })

        except Exception as e:
            print(f"Error extracting review: {e}")
            continue

    return reviews_data

注意点が1つあります。一部のレビューには「More」ボタンがあり、本文の全文を隠していることがあります。そのボタンをクリックしてレビューを展開してから本文を取得しようと試みています。常に完璧に動くわけではありませんが、ほとんどの場合に対応できます。

ステップ5:すべてをつなげる

では、これまでの関数を実際に実行できる1つのスクリプトにまとめましょう。

def scrape_google_reviews(place_url, max_reviews=100):
    """Main function to scrape Google Maps reviews."""
    p, browser, context = create_browser()
    page = context.new_page()

    try:
        # Step 1: Open the reviews panel
        open_reviews_panel(page, place_url)

        # Step 2: Scroll to load reviews
        scroll_reviews(page, max_reviews)

        # Step 3: Extract review data
        reviews = extract_reviews(page)

        # Step 4: Save to CSV
        df = pd.DataFrame(reviews)
        filename = 'google_reviews.csv'
        df.to_csv(filename, index=False, encoding='utf-8')
        print(f"\\nSaved {len(reviews)} reviews to {filename}")
        print(f"Average rating: {df['rating'].mean():.1f} stars")

        return reviews

    finally:
        browser.close()
        p.stop()


# Run the scraper
if __name__ == '__main__':
    url = 'https://www.google.com/maps/place/YOUR_BUSINESS_URL'
    reviews = scrape_google_reviews(url, max_reviews=200)
    print(f"\\nDone! Scraped {len(reviews)} reviews")

YOUR_BUSINESS_URLを実際のGoogle Mapsのリンクに差し替えるだけです。Google Mapsに行って任意のビジネスを検索し、ブラウザのアドレスバーからURLをコピーしてください。そのURLをそこに入れます。

方法2:Seleniumでレビューをスクレイピングする

すでにSeleniumを使ったことがあり、慣れているという方もいるでしょう。あるいは、何らかの理由で業務環境がPlaywrightをサポートしていない場合もあるかもしれません。それでも問題ありません — Seleniumでも十分に作業はこなせます。コードは少し冗長になりますが、ロジックは同じです。

Seleniumのセットアップ

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
import pandas as pd
import time
import random

def create_selenium_driver():
    """Create a Selenium Chrome driver with stealth settings."""
    options = webdriver.ChromeOptions()
    options.add_argument('--disable-blink-features=AutomationControlled')
    options.add_argument('--window-size=1366,768')
    options.add_argument('--lang=en-US')
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_experimental_option('useAutomationExtension', False)

    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service, options=options)

    # Remove the webdriver flag
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
        'source': '''
            Object.defineProperty(navigator, 'webdriver', {get: () => undefined})
        '''
    })

    return driver

Seleniumレビュースクレイパー

def scrape_with_selenium(place_url, max_reviews=100):
    """Scrape Google Maps reviews using Selenium."""
    driver = create_selenium_driver()

    try:
        driver.get(place_url)
        time.sleep(3)

        # Accept cookies
        try:
            cookie_btn = WebDriverWait(driver, 5).until(
                EC.element_to_be_clickable((By.XPATH,
                    '//button[contains(text(), "Accept all")]'))
            )
            cookie_btn.click()
        except:
            pass

        # Click Reviews tab
        reviews_tab = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR,
                'button[data-tab-index="1"]'))
        )
        reviews_tab.click()
        time.sleep(2)

        # Scroll to load reviews
        scrollable = driver.find_element(By.CSS_SELECTOR,
            'div.m6QErb.DxyBCb.kA9KIf.dS8AEf')

        last_count = 0
        for _ in range(50):
            driver.execute_script(
                'arguments[0].scrollTop = arguments[0].scrollHeight',
                scrollable
            )
            time.sleep(random.uniform(1.5, 3.0))

            reviews = driver.find_elements(By.CSS_SELECTOR,
                'div.jftiEf.fontBodyMedium')
            if len(reviews) >= max_reviews or len(reviews) == last_count:
                break
            last_count = len(reviews)

        # Parse with BeautifulSoup for easier extraction
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        review_elements = soup.select('div.jftiEf.fontBodyMedium')

        reviews_data = []
        for el in review_elements:
            name = el.select_one('.d4r55')
            rating = el.select_one('.kvMYJc')
            text = el.select_one('.wiI7pd')
            date = el.select_one('.rsqaWe')

            rating_val = 0
            if rating and rating.get('aria-label'):
                import re
                m = re.search(r'(\\d+)', rating['aria-label'])
                rating_val = int(m.group(1)) if m else 0

            reviews_data.append({
                'reviewer_name': name.text if name else 'Anonymous',
                'rating': rating_val,
                'review_text': text.text if text else '',
                'review_date': date.text if date else '',
            })

        # Save to CSV
        df = pd.DataFrame(reviews_data)
        df.to_csv('reviews_selenium.csv', index=False)
        print(f"Saved {len(reviews_data)} reviews")
        return reviews_data

    finally:
        driver.quit()

PlaywrightとSelenium — どちらを選ぶべき?

これはよく聞かれる質問です。両者を並べて比較してみましょう。

機能 Playwright Selenium
速度より高速(async対応)より低速
自動待機標準搭載手動(WebDriverWait)
セットアップの容易さ非常に簡単ドライバ管理が必要
検出回避より優れたステルスオプションundetected-chromedriverが必要
コミュニティ急速に拡大中最大のコミュニティ
学習曲線中程度緩やか

私の率直な意見は? ゼロから始めるならPlaywrightで決まりです。書くコードは少なく済み、トラブルにも遭遇しにくいでしょう。ただし、すでにSeleniumのコードがどこかで稼働しているのなら、わざわざ書き直す強い理由はありません。

Googleにブロックされないようにする方法

ほとんどのチュートリアルが軽く流すパートですが、おそらくこれが一番重要なところです。Googleはボットの検出が本当に得意です。ただヘッドレスブラウザを立ち上げて彼らのサーバーを連打すれば、数分でブロックされます。レーダーをかいくぐる方法を以下で紹介します。

1. アクション間にランダムな待機を入れる

誰だってボタンをクリックしてから50ミリ秒後に次のボタンをクリックしたりはしません。実在の人間は、ためらい、文字を読み、気が散ったりするものです。スクレイパーも同じように振る舞わせましょう。

import random

def human_delay(min_sec=1.0, max_sec=3.0):
    """Wait a random amount of time to mimic human behavior."""
    delay = random.uniform(min_sec, max_sec)
    time.sleep(delay)

2. ユーザーエージェントを変える

毎回まったく同じブラウザフィンガープリントでリクエストを送ると、それだけで一発でバレます。複数を使い分けましょう。

USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4) AppleWebKit/537.36 Chrome/124.0.0.0',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/124.0.0.0',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Firefox/125.0',
]

user_agent = random.choice(USER_AGENTS)

3. プロキシを使う(特に大規模なジョブの場合)

数件程度のビジネスを超えてスクレイピングするようになったら、IPアドレスをローテーションさせたほうがよいでしょう。そうでなければ、Googleは1つの場所から何百ものリクエストが来ていることを察知し、シャットダウンしてきます。

def create_browser_with_proxy(proxy_url):
    """Launch browser through a proxy server."""
    p = sync_playwright().start()
    browser = p.chromium.launch(
        proxy={'server': proxy_url},
        headless=True,
    )
    return p, browser

4. スピードを欲張らない

できるだけ速くスクレイピングしたくなる気持ちは分かりますが、ここは辛抱が報われる場面です。私自身の経験で機能してきた、ざっくりとした目安をいくつか紹介します。

  • 1つのIPアドレスから1時間あたり10〜20ビジネス程度に抑える
  • 異なるビジネスページの読み込み間に3〜5秒待つ
  • レビューパネル内のスクロール操作の間に1〜3秒のポーズを入れる
  • 10〜15ビジネスごとに長めの休憩をとる — 30〜60秒くらい。コーヒーでも飲みに行きましょう。

よくある問題(と解決法)

必ず何らかの問題に遭遇します。誰でもそうです。よく見かけるものを以下にまとめます。

「レビューがまったく読み込まれない」

これは通常、Googleにボットだと見破られたか、ページレイアウトが変更されたことを意味します。最初に試すべきことは、headless=Falseに設定して、実際のブラウザウィンドウを目視で確認することです。CAPTCHAが出ていませんか? 全体を覆うCookieバナーは? 自分が想定していなかったポップアップで「Accept」をクリックするだけで解決することもあります。それ以外の場合は、GoogleがCSSクラスを変えたので、セレクタを更新する必要があります。

「数百件あるはずなのに10件しか取得できない」

スクロールが正しく機能していません。スクロール対象が正しいコンテナになっているかを再確認してください — メインのページではなく、レビューパネル内の特定のdivです。print(scrollable)を追加してNoneになっていないか確認しましょう。スクロール間のディレイを長くするのも有効です — Googleのサーバーが次のレビューを送るのに時間がかかっている場合があります。

「3〜4ビジネスは動くのに、その後ブロックされる」

スピードが速すぎます。ペースを落とし、ビジネス間のポーズを長くし、もしまだなら本気でプロキシの導入を検討してください。1つのIPからは1セッションあたり10〜20ビジネスというのが妥当な目安です。

「セレクタが何も見つけてくれない」

GoogleはCSSのクラス名を、思っている以上に頻繁に変えます。これが起きたときは、自分のブラウザでGoogle Mapsを開き、レビューを右クリックして「Inspect Element」をクリックし、現在のクラス名を確認します。そしてコードをそれに合わせて更新します。煩わしい作業ですが、Webスクレイピングをする以上避けられない部分です。

あるいはコードをスキップして — Livescraperを使う

ここまで、本記事のかなりの分量を使って、ゼロからスクレイパーを構築する方法を解説してきました。そして、上記のすべてが実際に動きます。しかし、これがメンテナンスゼロだと言ったら嘘になります。Googleがページレイアウトを変えれば、セレクタは壊れます。新しいアンチボット対策が導入されれば、プロキシは使えなくなります。1つを直すと、また別のものが壊れる。これの繰り返しです。

こうしたことに付き合わずにデータだけ欲しいなら、まさにそのためにLivescraperのReviews Scraperがあります。

自作する代わりにLivescraperを使う理由は?

機能 自作のPythonスクレイパー Livescraper
セットアップ時間数時間〜数日2分
メンテナンス継続的に必要(セレクタが壊れる)ゼロ — 私たちが対応します
検出回避プロキシとディレイを自分で管理プロキシローテーション標準搭載
スケールマシンの性能に依存クラウドベース、無制限
出力形式CSV(手動エクスポート)CSV、JSON、Excel
コーディングの要否必要(Python)不要
コスト無料 + あなたの時間無料プランあり

使い方(本当に、3ステップです)

  1. アカウントを作成app.livescraper.comにアクセスしてサインアップします。無料で始められます。
  2. スクレイピング対象を伝える — Google MapsのURLを貼り付けるか、ビジネス名を入力するだけです。タスクタイプとして「Reviews Scraper」を選びます。
  3. ファイルを取得する — 「Start Scraping」を押し、完了したら結果をCSVまたはJSONでダウンロードします。

セットアップすべきPython環境もなく、買うべきプロキシもなく、壊れたセレクタを直す必要もありません。データだけが手に入ります。営業トークに聞こえるかもしれませんが、GoogleがCSSクラスを変えたせいで深夜2時にスクレイパーをデバッグして数時間溶かした経験があれば……このシンプルさのありがたみを実感するはずです。

Livescraperで他に何ができるのか?

レビューだけがすべてではありません。すでにレビューデータを取得しているなら、他のビジネスデータも必要になる可能性が高いでしょう。

  • Google Maps Scraper — Mapsの任意の検索結果からビジネス名、住所、電話番号、ウェブサイト、評価を取得
  • Email Scraper — ビジネスのウェブサイトからメールアドレスを取得(アウトリーチに最適)
  • Google Search Scraper — Google検索結果からURL、タイトル、スニペットを抽出
  • B2B Lead Database — 検証済みの連絡先情報を備えた、構築済みのビジネスリードデータベース。スクレイピング不要

合法性についての簡単な一言

私は弁護士ではないので、これは法的助言ではありません。しかし、Googleレビューのような公開データのスクレイピングについて一般的に理解されていることをお伝えします。

たぶん問題ないケース

  • 公開レビューデータを自身の調査や分析のためにスクレイピングしている
  • 自社ビジネスのレビューを一括取得している
  • 適切に匿名化されたデータで学術研究を行っている
  • 社内のビジネス上の意思決定のために競合分析を行っている

注意が必要なケース

  • レビューをコピーし、自分のウェブサイトに再掲載している
  • あまりに激しくスクレイピングして、実質的にGoogleのサーバーをDDoSしている状態になっている
  • GDPRやプライバシー法を考慮せずに、レビュアーの個人情報を保存している
  • 特定のレビュアーを標的にしたり嫌がらせをするためにデータを利用している(言うまでもなく、絶対にやってはいけません)

一般的な良い習慣

  • 始める前にrobots.txtを確認する — サイト運営者が何を望んでいるかが書かれています
  • リクエストレートを適切な範囲に保つ
  • 個人データは、必要な期間以上に保持しない
  • 正当なビジネス用途に限定する
  • コンプライアンスが懸念事項なら、Livescraperのようなサービスは多くを代行してくれます

まとめ

多くの内容を扱いましたが、これでPythonを使ったGoogle Mapsレビューのスクレイピング方法について、しっかりとした理解が得られたはずです。Playwrightを使ったフルのアプローチ(新規プロジェクトなら私はこちらを選びます)、Seleniumのアプローチ(慣れているならそれでまったく問題ありません)、検出回避のテクニック、そして最もよくあるトラブルへの対処法を解説しました。

実のところ、スクレイパーを構築することは簡単な部分です。長期にわたって安定して動かし続けること — Googleの絶え間ない変更に対応し、プロキシを管理し、壊れたセレクタを直すこと — そこにこそ本当の時間投資が必要になります。だからこそ、ニーズによっては、そういったすべてを裏で処理してくれるツールを使うほうが理にかなっている場合もあります。

それに魅力を感じるなら、Livescraperをお試しください。無料プランがあるので、コミットなしで試してみることができます。DIY派なら、上記のコードに必要なものはすべて揃っています。プロジェクトの成功を願っています!