如何從 Google 地圖中提取商家名稱、評分和評論
了解如何使用 Python 和 TalorData SERP API 從類似 Google 地圖的搜尋結果中提取商家名稱、評分、評論數量、類別、地址、電話號碼、網站及地點 ID。
Google Maps 是分析本地商家可見度的重要資料來源。如果你想研究餐廳、牙醫診所、飯店、健身房、水電工、代理商或其他本地商家類別,通常最先需要的是幾個基礎欄位:
|
欄位 |
用途 |
|
Business name |
識別商家 |
|
Rating |
判斷口碑品質 |
|
Review count |
判斷評論量和信任度 |
|
Category |
商家分類 |
|
Address |
匹配地區市場 |
|
Phone number |
用於 lead workflows |
|
Website |
用於資料補全 |
|
Position |
判斷 local search visibility |
|
Place ID / data CID |
用於去重和追蹤 |
真正麻煩的不是理解這些欄位,而是穩定地收集它們。
如果用 browser automation 手動抓 Google Maps,頁面結構、動態載入、結果滾動、不同地點返回不同結果,都會讓流程變脆。SERP API workflow 的價值,就是把 Google Maps-style results 變成更容易解析、保存和比較的 structured JSON。TalorData SERP API 支援 structured JSON / HTML output、geo-targeted SERP data,也覆蓋 Maps 和 Local 這類 Google result types。
這篇會示範如何用 Python 和 TalorData 提取 Google Maps 中的 business names、ratings 和 review counts。
我們要做什麼?
這篇會建立一個 Python script,用來:
-
發送 Google Maps search query
-
從 TalorData 取得 structured JSON
-
提取 business names、ratings、review counts、categories、addresses、websites 和 phone numbers
-
標準化資料
-
匯出 CSV
流程如下:
Search query + location
↓
TalorData SERP API
↓
Google Maps results in JSON
↓
Extract business fields
↓
Save CSV or database
可以提取哪些資料?
本地商家資料通常先從這些欄位開始:
|
Field |
Example |
|
|
Example Coffee |
|
|
4.6 |
|
|
1280 |
|
|
Coffee shop |
|
|
123 Example St, New York |
|
|
+1 212-000-0000 |
|
|
https://example.com |
|
|
ChIJExample |
|
|
123456789 |
|
|
1 |
|
|
40.7455 |
|
|
-74.0083 |
|
|
Google Maps listing URL |
在 Maps workflow 裡,business name、place ID、address、coordinates、category、rating、review count、rank position、opening status、phone number、website、Google Maps URL、thumbnail 和 price level 都是常見可用欄位。
Step 1:準備 API key
將 TalorData API key 和 endpoint 存成環境變數。
export TALORDATA_API_KEY="your_api_key_here"
export TALORDATA_SERP_ENDPOINT="your_talordata_serp_endpoint_here"
Windows PowerShell:
setx TALORDATA_API_KEY "your_api_key_here"
setx TALORDATA_SERP_ENDPOINT "your_talordata_serp_endpoint_here"
安裝 Python dependencies:
pip install requests pandas
Step 2:發送 Google Maps request
Request 需要 query 和 location context。對 local search 來說,座標通常比城市名稱更精準,因為 Google Maps results 可能街區之間就有差異。
import os
import requests
from typing import Any, Dict, Optional
TALORDATA_API_KEY = os.getenv("TALORDATA_API_KEY")
TALORDATA_SERP_ENDPOINT = os.getenv("TALORDATA_SERP_ENDPOINT")
def fetch_google_maps(
query: str,
ll: str,
hl: str = "en",
gl: str = "us",
google_domain: str = "google.com",
no_cache: bool = True,
extra_params: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
"""
Fetch Google Maps-style search results with TalorData SERP API.
ll format example:
@40.7455096,-74.0083012,14z
"""
if not TALORDATA_API_KEY:
raise RuntimeError("Missing TALORDATA_API_KEY environment variable.")
if not TALORDATA_SERP_ENDPOINT:
raise RuntimeError("Missing TALORDATA_SERP_ENDPOINT environment variable.")
payload: Dict[str, Any] = {
"engine": "google_maps",
"type": "search",
"q": query,
"ll": ll,
"hl": hl,
"gl": gl,
"google_domain": google_domain,
"no_cache": no_cache
}
if extra_params:
payload.update(extra_params)
response = requests.post(
TALORDATA_SERP_ENDPOINT,
json=payload,
headers={
"Authorization": f"Bearer {TALORDATA_API_KEY}",
"Content-Type": "application/json"
},
timeout=30
)
response.raise_for_status()
return response.json()
基本執行:
if __name__ == "__main__":
data = fetch_google_maps(
query="coffee shops",
ll="@40.7455096,-74.0083012,14z",
hl="en",
gl="us"
)
print(data)
Step 3:檢查 raw response
寫 parser 前,先看 JSON structure。
import json
print(json.dumps(data, indent=2, ensure_ascii=False)[:5000])
結果可能放在這類欄位中:
local_results
maps_results
place_results
results
organic_results
不同 result type 可能有不同容器。Parser 不要一開始就做成石碑,留一點彈性。
Step 4:解析商家名稱、評分和評論數
下面的 parser 會檢查多個可能的 result containers,並提取常見商家欄位。
from typing import Any, Dict, List
def get_first_available_list(data: Dict[str, Any], keys: List[str]) -> List[Dict[str, Any]]:
for key in keys:
value = data.get(key)
if isinstance(value, list):
return value
return []
def parse_business_results(data: Dict[str, Any]) -> List[Dict[str, Any]]:
items = get_first_available_list(
data,
keys=[
"local_results",
"maps_results",
"place_results",
"results",
"organic_results"
]
)
rows = []
for index, item in enumerate(items, start=1):
gps = item.get("gps_coordinates") or {}
links = item.get("links") or {}
rows.append({
"position": item.get("position", index),
"business_name": item.get("title") or item.get("name"),
"rating": item.get("rating"),
"review_count": item.get("reviews") or item.get("review_count"),
"category": item.get("type") or item.get("category"),
"address": item.get("address"),
"phone": item.get("phone"),
"website": item.get("website") or links.get("website"),
"place_id": item.get("place_id"),
"data_cid": item.get("data_cid") or item.get("cid"),
"maps_url": item.get("link") or item.get("maps_url"),
"latitude": gps.get("latitude") or item.get("latitude"),
"longitude": gps.get("longitude") or item.get("longitude"),
"open_state": item.get("open_state") or item.get("hours"),
"price_level": item.get("price") or item.get("price_level")
})
return rows
使用方式:
data = fetch_google_maps(
query="coffee shops",
ll="@40.7455096,-74.0083012,14z"
)
businesses = parse_business_results(data)
for business in businesses[:5]:
print(
business["position"],
business["business_name"],
business["rating"],
business["review_count"]
)
Step 5:匯出 CSV
CSV 適合快速檢查、人工 QA、Excel 分析、CRM 匯入或 BI dashboard。
import pandas as pd
data = fetch_google_maps(
query="coffee shops",
ll="@40.7455096,-74.0083012,14z"
)
businesses = parse_business_results(data)
df = pd.DataFrame(businesses)
df.to_csv("google_maps_businesses.csv", index=False)
print(df.head())
範例表格:
|
position |
business_name |
rating |
review_count |
category |
|
1 |
Example Coffee |
4.6 |
1280 |
Coffee shop |
|
2 |
Sample Cafe |
4.4 |
760 |
Cafe |
|
3 |
Local Roasters |
4.7 |
420 |
Coffee roasters |
Step 6:清理 rating 和 review count
Rating 和 review count 可能是 string,也可能是 number。分析前先轉成數字。
df["rating_num"] = pd.to_numeric(df["rating"], errors="coerce")
df["review_count_num"] = pd.to_numeric(df["review_count"], errors="coerce")
按口碑強度排序:
top_reputation = df.sort_values(
by=["rating_num", "review_count_num"],
ascending=[False, False]
)
top_reputation.to_csv("top_rated_businesses.csv", index=False)
print(top_reputation[[
"business_name",
"rating",
"review_count",
"category",
"address"
]].head(10))
Rating 和 review count 要一起看。
|
Case |
Meaning |
|
High rating + high review count |
口碑強 |
|
High rating + low review count |
分數高,但樣本少 |
|
Low rating + high review count |
知名度高,但有口碑風險 |
|
No rating |
可能是新 listing 或資料不完整 |
|
High position + weak reviews |
可見度強,但信任感弱 |
4.9 分但只有 12 則評論,和 4.6 分但有 2,000 則評論,不是同一件事。
Step 7:加入 search context
如果要比較不同時間的結果,每一列都要保存 search context。
from datetime import datetime, timezone
def add_search_context(
rows: List[Dict[str, Any]],
query: str,
ll: str,
hl: str,
gl: str
) -> List[Dict[str, Any]]:
collected_at = datetime.now(timezone.utc).isoformat()
for row in rows:
row["query"] = query
row["ll"] = ll
row["hl"] = hl
row["gl"] = gl
row["collected_at"] = collected_at
return rows
使用:
query = "coffee shops"
ll = "@40.7455096,-74.0083012,14z"
hl = "en"
gl = "us"
data = fetch_google_maps(query=query, ll=ll, hl=hl, gl=gl)
rows = parse_business_results(data)
rows = add_search_context(rows, query=query, ll=ll, hl=hl, gl=gl)
pd.DataFrame(rows).to_csv("google_maps_snapshot.csv", index=False)
這樣就能追蹤:
|
Change |
Meaning |
|
Position changed |
本地排名變化 |
|
Rating changed |
口碑變化 |
|
Review count increased |
顧客回饋增加 |
|
Business disappeared |
可見度變化 |
|
New competitor appeared |
市場變化 |
|
Website or phone appeared |
Listing completeness 改善 |
Step 8:去重商家
Business names 可能變化,地址格式也可能不同。去重時優先使用穩定 ID。
建議順序:
-
place_id -
data_cid -
Business name + address
-
Business name + latitude + longitude
def build_business_key(row: Dict[str, Any]) -> str:
if row.get("place_id"):
return f"place_id:{row['place_id']}"
if row.get("data_cid"):
return f"data_cid:{row['data_cid']}"
name = str(row.get("business_name") or "").lower().strip()
address = str(row.get("address") or "").lower().strip()
return f"name_address:{name}|{address}"
df["business_key"] = df.apply(lambda row: build_business_key(row.to_dict()), axis=1)
df = df.drop_duplicates(subset=["business_key"])
當你跨多個座標收集同一類商家時,這一步尤其重要。
Step 9:跨多個地點搜尋
Local SEO 只查一個座標通常不夠。可以建立 coordinate grid。
locations = [
{
"label": "Manhattan West",
"ll": "@40.7455096,-74.0083012,14z"
},
{
"label": "Times Square",
"ll": "@40.758896,-73.985130,14z"
},
{
"label": "Lower Manhattan",
"ll": "@40.707491,-74.011276,14z"
}
]
all_rows = []
for location in locations:
data = fetch_google_maps(
query="coffee shops",
ll=location["ll"],
hl="en",
gl="us"
)
rows = parse_business_results(data)
for row in rows:
row["grid_location"] = location["label"]
rows = add_search_context(
rows,
query="coffee shops",
ll=location["ll"],
hl="en",
gl="us"
)
all_rows.extend(rows)
pd.DataFrame(all_rows).to_csv("google_maps_multi_location.csv", index=False)
這能回答:
|
Question |
What to measure |
|
哪些商家出現最頻繁? |
Presence across locations |
|
哪個商家平均排名最好? |
Local visibility |
|
哪些競品評論更強? |
Rating + review count |
|
哪些區域競爭更激烈? |
Strong listings 數量 |
|
哪些地點覆蓋較弱? |
Missing 或 low-quality results |
常見錯誤
只提取 business name
Business name 本身不夠。應盡量一起提取 rating、review count、category、address、phone、website 和 place ID。
忽略 location
Google Maps results 是本地結果。要保存 coordinate、zoom level、language 和 country context。
把 rating 當成全部口碑
Rating 必須搭配 review count。高分但評論少,信號可能不穩。
不做去重
同一商家可能出現在多個搜尋中。優先使用 place_id 或 data_cid 去重。
覆蓋歷史快照
如果要做 monitoring,應 append 新資料,而不是替換舊檔案。
不保存 raw JSON
開發階段要保存 raw response。Parser 出問題時會好修很多。
結語
從 Google Maps 提取 business names、ratings 和 reviews,適合 local SEO、lead generation、competitor research、market analysis、review monitoring 和 AI agents。
乾淨流程是:
-
發送 local Maps query
-
取得 structured JSON
-
提取 business name、rating、review count、category、address、website、phone 和 place ID
-
保存 search context
-
匯出 CSV 或寫入 database
-
持續追蹤變化
Google Maps 像一條擁擠街道。結構化資料會把它變成有路燈的表格。開始免費試用Google Maps API>>