如何使用 TalorData 抓取 Google 地圖搜尋結果

了解如何使用 TalorData SERP API 抓取 Google 地圖搜尋結果。本技術指南涵蓋了地圖參數、Python requests 庫的使用、本地商家資訊欄位(包括評分、評論、地址、電話號碼、網站、地點 ID 和座標)、CSV 匯出以及本地 SEO 工作流程。

talor ai
最后更新于
10 分钟阅读

Google Maps results 是典型的 local-intent data。它能告訴你某個查詢下哪些商家出現、排名如何、評價強不強、聯絡方式是否完整,以及商家在本地市場中的可見度。

如果你在做 local SEO tools、lead generation workflows、market research dashboards、competitor monitors 或 AI agents,Google Maps data 可以回答這些問題:

問題

為什麼重要

“dentist near me” 會出現哪些商家?

Local visibility

指定座標附近,哪個競品排名更高?

Local SEO tracking

哪些商家 rating 和 review count 更強?

Reputation analysis

哪些 listing 有 phone 和 website?

Lead enrichment

哪些區域競爭更密集?

Market research

哪些 listing 在多個城市都出現?

Expansion planning

AI agent 應該推薦哪些本地商家?

AI workflow context

這篇指南會建立一個 Python workflow:把 Google Maps query 發送到 TalorData,取得 structured JSON,提取本地商家欄位,最後匯出 CSV。

整體流程:

Search query + map location
   ↓
TalorData SERP API
   ↓
Google Maps results in JSON
   ↓
Parse business fields
   ↓
Normalize place data
   ↓
Export to CSV or database

什麼是抓取 Google Maps search results?

這裡的 “scraping Google Maps”,指的是透過 TalorData SERP API 收集結構化 Google Maps-style search results。

它不是控制瀏覽器、手動滾動頁面,或從 Google Maps 介面抓 HTML。

我們要收集的是這些欄位:

Field

Example

Business name

Blue Bottle Coffee

Position

1

Rating

4.5

Review count

1,240

Category

Coffee shop

Address

123 Example St, New York

Phone number

+1 212-000-0000

Website

https://example.com

Google Maps URL

Maps listing link

Place ID / data CID

Unique place reference

Latitude / longitude

Map coordinates

Opening status

Open now / closed

Price level

$, $$, $$$

TalorData Google Maps response 可用於 local business search workflows,並可在可用時返回 business name、place ID、address、coordinates、category、rating、review count、rank position、opening status、phone number、website、Google Maps URL、thumbnail 和 price level 等欄位。

什麼時候適合使用 Google Maps SERP API?

當你的問題和 local visibility 有關,就適合使用 Google Maps search results。

Use case

Example

Local SEO rank tracking

在不同座標追蹤 “plumber near me”

Lead generation

收集帶 phone 和 website 的本地商家

Competitor research

比較 rating、reviews 和 positions

Market analysis

按城市統計某品類商家

Franchise monitoring

監控品牌在多市場的可見度

Review intelligence

追蹤 rating 和 review count

AI agents

把本地商家選項餵給推薦流程

Google Maps rankings 對 location 很敏感。同一個 query,在不同座標附近可能返回不同商家。所以 location control 很重要。

核心 Google Maps 參數

先從這些參數開始。

Parameter

Required

Purpose

Example

engine

Yes

選擇 Google Maps search

google_maps

q

Search queries

商家、品類或 local intent query

coffee shops

ll

建議使用

Latitude、longitude 和 zoom

@40.7455096,-74.0083012,14z

type

Optional

Search mode

searchplace

place_id

Place lookup

Google Maps place reference

ChIJ...

data_cid

Place lookup

Google CID-style place reference

123456789

google_domain

Optional

Google domain

google.com

hl

Optional

介面語言

en

gl

Optional

國家上下文

us

no_cache

Optional

Freshness control

true

Google Maps requests 中,ll 使用 @latitude,longitude,scale 這類座標格式,Maps search type 支援 search-style 和 place-style workflow。

Search mode vs place mode

通常有兩種使用方式。

Search mode

當你需要一組商家列表時,用 search mode。

範例:

coffee shops near Manhattan
dentists in Austin
hotels near JFK Airport
plumbers in Chicago
restaurants near Times Square

Search request 需要 query 和 location context。

{
  "engine": "google_maps",
  "type": "search",
  "q": "coffee shops",
  "ll": "@40.7455096,-74.0083012,14z",
  "hl": "en",
  "gl": "us"
}

Place mode

當你想查某個已知商家的詳細資料時,用 place mode。

你可以使用之前 search result 中的 place_iddata_cid

{
  "engine": "google_maps",
  "type": "place",
  "place_id": "ChIJExamplePlaceId",
  "hl": "en",
  "gl": "us"
}

常見流程:

Search query
   ↓
Get local business results
   ↓
Extract place_id or data_cid
   ↓
Request place details
   ↓
Store richer business data

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:建立可重用 Python client

這個 function 會發送 Google Maps search request 並返回 JSON。

如果你的 TalorData account 使用不同 request style,請調整 endpoint 或 authentication format。

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 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)

    headers = {
        "Authorization": f"Bearer {TALORDATA_API_KEY}",
        "Content-Type": "application/json"
    }

    response = requests.post(
        TALORDATA_SERP_ENDPOINT,
        json=payload,
        headers=headers,
        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。

import json

print(json.dumps(data, indent=2, ensure_ascii=False)[:5000])

可以找這類 result arrays:

local_results
maps_results
place_results
results
organic_results

實際 top-level field 可能會因 response type 而變。不要太早把 parser 刻在石頭上。先看洞穴牆,再拿鑿子。

Step 4:解析 Google Maps results

下面是一個保守 parser,會檢查幾個可能的結果容器,並提取常見本地商家欄位。

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_maps_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),
            "title": item.get("title") or item.get("name"),
            "place_id": item.get("place_id"),
            "data_cid": item.get("data_cid") or item.get("cid"),
            "category": item.get("type") or item.get("category"),
            "rating": item.get("rating"),
            "review_count": item.get("reviews") or item.get("review_count"),
            "address": item.get("address"),
            "phone": item.get("phone"),
            "website": item.get("website") or links.get("website"),
            "maps_url": item.get("link") or item.get("maps_url"),
            "thumbnail": item.get("thumbnail"),
            "price_level": item.get("price") or item.get("price_level"),
            "open_state": item.get("open_state") or item.get("hours"),
            "latitude": gps.get("latitude") or item.get("latitude"),
            "longitude": gps.get("longitude") or item.get("longitude")
        })

    return rows

使用:

data = fetch_google_maps(
    query="coffee shops",
    ll="@40.7455096,-74.0083012,14z"
)

rows = parse_maps_results(data)

for row in rows[:5]:
    print(row["position"], row["title"], row["rating"], row["review_count"])

Step 5:保存成 CSV

import pandas as pd


data = fetch_google_maps(
    query="coffee shops",
    ll="@40.7455096,-74.0083012,14z"
)

rows = parse_maps_results(data)

df = pd.DataFrame(rows)
df.to_csv("google_maps_results.csv", index=False)

print(df.head())

CSV 可能長這樣:

position

title

rating

review_count

category

address

1

Example Coffee

4.6

1280

Coffee shop

123 Example St

2

Sample Cafe

4.4

760

Cafe

45 Sample Ave

3

Local Roasters

4.7

420

Coffee roasters

88 Market Rd

Step 6:加入 search context

沒有 context 的 Maps result,很難在之後比較。

每一列都應該保存 query、coordinate、language、country 和 timestamp。

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_maps_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 added or removed

Listing completeness 變化

Step 7:搜尋多個座標

對 local SEO 來說,只查一個 city-level location 通常太粗。

更好的方式,是對同一個 query 跑 coordinate grid。

locations = [
    {
        "name": "Manhattan West",
        "ll": "@40.7455096,-74.0083012,14z"
    },
    {
        "name": "Times Square",
        "ll": "@40.758896,-73.985130,14z"
    },
    {
        "name": "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_maps_results(data)

    for row in rows:
        row["grid_location"] = location["name"]

    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_grid_results.csv", index=False)

這可以幫你發現:

Signal

Example

Local rank variation

某咖啡店在一個座標 #1,在另一個座標 #8

Competitor clusters

某區域競品密集

Visibility gaps

商家離開小半徑後就消失

Review advantage

評論更強的競品更常出現

Expansion areas

某些區域強 listing 較少

Step 8:取得 place-level details

Search result 給你一組列表。Place lookup 可以讓你深入看一個商家。

使用 search result 中的 place_iddata_cid

def fetch_google_maps_place(
    place_id: Optional[str] = None,
    data_cid: Optional[str] = None,
    hl: str = "en",
    gl: str = "us",
    google_domain: str = "google.com"
) -> Dict[str, Any]:
    if not place_id and not data_cid:
        raise ValueError("Provide either place_id or data_cid.")

    payload: Dict[str, Any] = {
        "engine": "google_maps",
        "type": "place",
        "hl": hl,
        "gl": gl,
        "google_domain": google_domain
    }

    if place_id:
        payload["place_id"] = place_id

    if data_cid:
        payload["data_cid"] = data_cid

    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()

範例:

rows = parse_maps_results(data)

first_place_id = rows[0].get("place_id")
place_data = fetch_google_maps_place(place_id=first_place_id)

print(json.dumps(place_data, indent=2, ensure_ascii=False)[:3000])

當你想在搜尋後補充特定商家詳情時,用 place mode。

Step 9:完整 script

下面是一個完整範例:搜尋 Google Maps、解析本地商家欄位、加入 context,最後匯出 CSV。

import os
import json
import requests
import pandas as pd
from datetime import datetime, timezone
from typing import Any, Dict, List, 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]:
    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()


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_maps_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),
            "title": item.get("title") or item.get("name"),
            "place_id": item.get("place_id"),
            "data_cid": item.get("data_cid") or item.get("cid"),
            "category": item.get("type") or item.get("category"),
            "rating": item.get("rating"),
            "review_count": item.get("reviews") or item.get("review_count"),
            "address": item.get("address"),
            "phone": item.get("phone"),
            "website": item.get("website") or links.get("website"),
            "maps_url": item.get("link") or item.get("maps_url"),
            "thumbnail": item.get("thumbnail"),
            "price_level": item.get("price") or item.get("price_level"),
            "open_state": item.get("open_state") or item.get("hours"),
            "latitude": gps.get("latitude") or item.get("latitude"),
            "longitude": gps.get("longitude") or item.get("longitude")
        })

    return rows


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


def main() -> None:
    query = "coffee shops"
    ll = "@40.7455096,-74.0083012,14z"
    hl = "en"
    gl = "us"

    raw_data = fetch_google_maps(
        query=query,
        ll=ll,
        hl=hl,
        gl=gl
    )

    rows = parse_maps_results(raw_data)
    rows = add_search_context(rows, query=query, ll=ll, hl=hl, gl=gl)

    pd.DataFrame(rows).to_csv("google_maps_results.csv", index=False)

    with open("raw_google_maps_response.json", "w", encoding="utf-8") as file:
        json.dump(raw_data, file, ensure_ascii=False, indent=2)

    print(f"Saved {len(rows)} rows to google_maps_results.csv")
    print("Saved raw_google_maps_response.json")


if __name__ == "__main__":
    main()

應該保存哪些欄位?

大多數 Google Maps scraping workflows 可以先用這個 schema:

{
  "query": "coffee shops",
  "ll": "@40.7455096,-74.0083012,14z",
  "hl": "en",
  "gl": "us",
  "collected_at": "2026-06-30T09:00:00Z",
  "business": {
    "position": 1,
    "title": "Example Coffee",
    "place_id": "ChIJExample",
    "data_cid": "123456789",
    "category": "Coffee shop",
    "rating": 4.6,
    "review_count": 1280,
    "address": "123 Example St, New York, NY",
    "phone": "+1 212-000-0000",
    "website": "https://example.com",
    "maps_url": "https://...",
    "latitude": 40.7455,
    "longitude": -74.0083,
    "open_state": "Open",
    "price_level": "$$"
  }
}

進階 workflow 可以加:

Field

Use case

thumbnail

UI display

hours

Business availability

service_options

餐廳或服務篩選

popular_times

需求模式分析

reviews_summary

Reputation intelligence

owner_response

Review management

booking_link

Conversion tracking

menu_link

Restaurant intelligence

category_ids

Classification

raw_response

Debug 和 reprocessing

常見錯誤

沒有使用座標搜尋

對 Maps 來說,location 不是裝飾。需要 local precision 時,請使用 ll

比較不同 zoom level 的結果

14z16z 可能返回不同結果。保存完整 ll value。

只看 rating

4.8 分但只有 12 則評論,和 4.6 分但有 2,000 則評論,不是同一件事。Rating 和 review count 要一起看。

忽略 business identity

商家名稱可能會變。去重時優先使用 place_iddata_cid

不保存 raw JSON

開發階段一定要保存 raw response。後續調整 parser 會更容易。

忘記 timestamps

Maps data 會變。沒有 timestamp 的 snapshot,就像沒有標籤的化石。

結語

使用 TalorData 抓取 Google Maps search results,本質上是把 local search 變成 structured data。

先從 query、coordinate、language、country 和 Google Maps search type 開始。然後解析 business name、position、rating、reviews、category、address、phone、website、place ID、coordinates、opening status 和 Maps URL。

資料結構化後,就可以用於 local SEO、lead generation、competitor monitoring、market research、franchise tracking 和 AI agents。

Google Maps 是一個活著的本地市場。好的 API workflow,會把這個市場整理成系統能理解的資料列。

立即开展您的数据业务

加入全球最强大的代理网络

免费试用