如何使用 TalorData 抓取 Google 地图搜索结果

了解如何使用 TalorData SERP API 抓取 Google 地图搜索结果。本技术指南涵盖了地图参数、Python requests 库的使用、本地商家信息字段(包括评分、评论、地址、电话号码、网站、地点 ID 和坐标)、CSV 导出以及本地 SEO 工作流程。

如何使用 TalorData 抓取 Google 地图搜索结果
Marcus Bennett
最后更新于
6 分钟阅读

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,会把这个市场整理成系统能理解的数据列。

立即开展您的数据业务

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

免费试用