谷歌本地抓取器API:将本地包转换为JSON
Web Data Collection Specialist
关键要点:
- 一个请求,一个演员。 Scrapeless Scraper API 将 Google 本地套餐转化为针对
scraper.google.search演员的单个POST请求。无需浏览器驱动,无需解析标记。 tbm: "lcl"是开关。 发送输入{ "q": "旧金山的咖啡店", "tbm": "lcl" },演员将返回基于地图的商家列表,而不是网页 SERP。- 结构化字段,而不是原始 HTML。 响应是一个解析后的本地对象 —
local_results.places[],其中包含标题、评级、评论数量、地址、价格层级和照片缩略图—在顶层展平。 - 过滤器芯片也会带来。
suggested_searches携带了“立即开放 / 顶级评级 / 便宜”的芯片,作为随时可用的 Google URL,这样你可以在不重建的情况下切换同一查询。 - 没有代理,您的那边不需要防机器人处理。 住宅出口、地域路由和渲染在服务器端运行;您只需发送查询并读取 JSON。
- 免费开始。 新的 Scrapeless 账户包括免费的 Scraper API 额度 — 请在 app.scrapeless.com 注册。
介绍:将 Google 本地套餐转化为 JSON
Google 本地套餐是位于本地搜索顶部的商家列表的盒装集合 — 当某人查找“旧金山的咖啡店”或“离我最近的水管工”时,Google 显示的基于地图的卡片。每张卡片都包含一个名称、一个类别、一个星级评级、一个评论数量、一个地址和一个价格层级。它是用户实际点击的表面本地意图搜索,这使它成为许多实际工作背后的数据集:
- 本地排名跟踪 — 看到哪些商家在给定城市的查询中占据 1 到 N 的位置。
- 竞争监控 — 跟踪竞争对手的评级和评论数量随时间变化。
- 潜在客户列表 — 将排名在某个类别和地点查询中的商家拉入结构化表格。
- 评论与情感抽样 — 每张卡片显示一个代表性的评论片段,你可以大规模收集。
- 市场规模评估 — 统计某类商家在一个大城市中排名的数量及其评级分布。
手动提取这些套餐意味着要渲染一个 JavaScript 密集的搜索页面,通过 Google 的速率限制,并对变化的标记进行选择。Scraper API 完成这三项工作于服务器端并将解析后的对象交给您。
为什么选择 Scraper API
传统的本地抓取器是三个工作组合在一起:绕过防机器人层,渲染页面,以及解析卡片。Scrapeless Scraper API 将它们合并为一次呼叫。你只需指定 scraper.google.search 演员,提供一个查询和 tbm: "lcl",便可获得解析后的本地套餐。
- 无需维护浏览器和解析器。 演员会渲染和解析 Google 的本地结果;您接收到的是字段,而不是需要遍历的 DOM。
- 内置住宅出口和地域路由。 您发送查询字符串;演员处理网络层和 JavaScript 渲染。
- 一个密钥,一个形状。 单个
x-api-token认证调用,本地套餐总是以相同的解析形状返回,因此编写一次的客户端可以在不同查询和城市之间重用。
在 app.scrapeless.com 的免费计划中获取您的 API 密钥。Google 本地套餐位于 Deep SerpApi 家族中,和其他 Google 搜索界面一起,详见 定价 目录。
先决条件
- 一个 Scrapeless 账户和 API 密钥 — 请在 app.scrapeless.com 注册。
curl进行快速测试,或使用 Python 3.10+ 进行下面的客户端。- 对 HTTP 和 JSON 有基本了解。
将您的密钥存储在环境变量中,确保它不会出现在代码中:
bash
export SCRAPELESS_API_KEY=your_api_token_here
请求
本地套餐使用 v1 Scraper API 端点和 Google 搜索演员。选择本地套餐是一个输入字段 — tbm 设置为 lcl。
- 端点:
POST https://api.scrapeless.com/api/v1/scraper/request - 认证: 头部
x-api-token: $SCRAPELESS_API_KEY - 演员:
scraper.google.search(tbm: "lcl"选择本地套餐而不是网页 SERP)
请求体为 { "actor": "<name>", "input": { … } }:
json
{
"actor": "scraper.google.search",
"input": { "q": "旧金山的咖啡店", "tbm": "lcl" }
}
| 输入字段 | 必须 | 描述 |
|---|---|---|
q |
是 | 本地搜索查询 — 包含城市或地区以获取最相关的套餐(例如 旧金山的咖啡店) |
tbm |
是 | 设置为 lcl 以选择本地套餐;省略或更改以获取网页 SERP |
示例
最快的检查方式是使用一个 curl。它会发布演员和输入,并打印解析后的本地对象:
bash
curl -sS -X POST https://api.scrapeless.com/api/v1/scraper/request \
-H "Content-Type: application/json" \
-H "x-api-token: $SCRAPELESS_API_KEY" \
-d '{
"actor": "scraper.google.search",
"input": { "q": "旧金山的咖啡店", "tbm": "lcl" }
}'
同样的调用在 Python 中读取环境中的密钥并返回解析后的响应:
python
import os
import json
import requests
ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
def scrape_local(query: str) -> dict:
resp = requests.post(
ENDPOINT,
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
json={"actor": "scraper.google.search", "input": {"q": query, "tbm": "lcl"}},
timeout=120,
)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
data = scrape_local("旧金山的咖啡店")
for place in data["local_results"]["places"]:
print(place["position"], place["title"], place["rating"], place["address"])
scraper.google.search 将解析后的本地包扁平化到顶层——没有 result 包装需要解包。直接读取 local_results.places[]。
在免费计划中获取您的 API 密钥:app.scrapeless.com
您获得的返回结果
演员直接返回解析后的本地对象,以及指向存储的渲染 HTML 的 metadata 信封。对于 q: "旧金山的咖啡店",tbm: "lcl" 的捕获运行返回了 20 个排名的地方:
json
// 来自实时 scraper.google.search (tbm: "lcl") 运行的顶层形状。
// 缩略图 base64 和大多数 places[] 条目已修剪;字段值是真实的。
{
"local_results": {
"places": [
{
"position": 1,
"title": "The Coffee Berry SF",
"type": "咖啡店",
"rating": 4.9,
"reviews": 588,
"reviews_original": "(588)",
"price": "$",
"address": "1410 Lombard St",
"phone": " $1–10 ",
"hours": "4.9(588) ",
"extensions": ["浓缩咖啡美味,员工非常友好和热情。"],
"thumbnail": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABA…",
"place_id": "",
"place_id_search": "",
"lsig": "",
"gps_coordinates": { "latitude": 0, "longitude": 0 }
},
{
"position": 8,
"title": "Delah Coffee",
"type": "咖啡店",
"rating": 4.7,
"reviews": 1100,
"reviews_original": "(1.1K)",
"price": "$",
"address": "370 4th St",
"phone": "临窗自取",
"hours": "堂食",
"extensions": ["堂食", "临窗自取", "无接触配送"],
"thumbnail": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABA…",
"place_id": "",
"place_id_search": "",
"lsig": "",
"gps_coordinates": { "latitude": 0, "longitude": 0 }
}
]
},
"search_information": {
"query_displayed": "旧金山的咖啡店",
"organic_results_state": "精确拼写的结果",
"total_results": 0,
"time_taken_displayed": ""
},
"suggested_searches": [
{
"name": "现在开放",
"q": "现在开放的旧金山咖啡店",
"link": "https://www.google.com/search?…&udm=1&q=coffee+shops+in+San+Francisco+open+now",
"uds": "",
"thumbnail": ""
}
],
"pagination": {},
"metadata": {
"engine": "google.search",
"rawUrl": "https://api.scrapeless.com/storage/scrapeless.scraper.google.search/…html"
}
}
每个 places[] 卡片上的字段:
| 字段 | 类型 | 描述 |
|---|---|---|
position |
数字 | 在本地包中的排名,基于 1 |
title |
字符串 | 商家名称 |
type |
字符串 | 商家类别,例如 咖啡店(原始值带有前导空格) |
rating |
数字 | 星级评分,例如 4.9 |
reviews |
数字 | 规范化为整数的评论数量,例如 588(3.4K 变为 3400) |
reviews_original |
字符串 | Google 显示的评论数量,例如 (3.4K) |
price |
字符串 | 价格级别,例如 $ |
address |
字符串 | 街道地址,例如 1410 Lombard St |
phone |
字符串 | 免费文本卡片栏 — 请参见下面的说明 |
hours |
字符串 | 免费文本卡片栏 — 请参见下面的说明 |
extensions |
字符串[] | 代表性评论片段,或者用于列出订购选项的卡片服务选项列表 |
thumbnail |
字符串 | 内联 data:image/jpeg;base64,… 的地方照片 |
place_id / place_id_search / lsig |
字符串 | 地点识别符;在此捕获中为空 |
gps_coordinates |
对象 | { latitude, longitude }; 在此捕获中的 0/0 |
卡片周围的顶层键:
| 键 | 内容 |
|---|---|
local_results.places[] |
排名的商业卡片 |
search_information |
查询回显和结果状态 |
suggested_searches[] |
本地过滤芯片(立即开放 / 高评分 / 廉价 / 高档 / 外卖)作为 Google URLs |
pagination |
分页链接(此查询为空) |
metadata |
engine 以及 rawUrl,渲染 HTML 的存储副本 |
从捕获结构的几个诚实观察:
- 对象已被扁平化。
local_results.places[]是你遍历的数组 — 没有result包装器,不像其他一些角色。 reviews和reviews_original以两种方式承载相同的计数。 一个是用于数学的整数,一个是 Google 的显示字符串 ((3.4K))。请根据你的管道需要读取。phone和hours跟踪 Google 在每个卡片槽中渲染的内容。 对于许多本地卡片,这是一条价格区间("$1–10")或服务标志(Curbside pickup,Dine-in),而不是字面上的电话号码或营业时间。将两者视为自由文本,并在依赖之前进行验证。extensions按卡片分支。 大多数卡片返回一个评论片段;具有订单选项的卡片返回服务列表(Dine-in,Curbside pickup,No-contact delivery)。检查你获得的是什么。- 标识符和坐标字段可能会为空。
place_id、place_id_search、lsig和gps_coordinates在架构中存在,但每张卡片可能为空或为零 — 将缺失字段视为可空的。 metadata.rawUrl是你的逃生通道。 如果你需要解析对象中未显现的字段,它存储渲染的 HTML。
结论
抓取 Google 本地包归结为一个决定和一个请求:选择 scraper.google.search 角色,发送 { "q": "<query>", "tbm": "lcl" } 以及你的 x-api-token,并将 local_results.places[] 作为解析的 JSON 回读。代理旋转、JavaScript 渲染和解析都在服务器端运行,因此同一个客户端通过更改查询字符串可以指向任何城市或类别。对于 Google 搜索的 AI 回答部分,Google AI 概述抓取指南 以相同方式讲解如何捕获答案块及其引用。在 q 中固定地方,保持 tbm: "lcl" 设置,并将自由文本和标识符字段视为可空的。
准备好构建你的 AI 驱动的本地搜索管道了吗?
加入我们的社区,领取免费计划并与构建本地搜索管道的开发者连接:Discord · Telegram。
在 app.scrapeless.com 注册,获取免费的抓取 API 积分,并将 scraper.google.search 角色指向你的管道所需的查询、城市和类别。
常见问题
问:抓取 Google 本地是否合法?
本地包是公开可见的数据。规则因司法管辖区和 Google 的服务条款而异,因此在大规模运行之前,请查看相关的服务条款并咨询律师以确定你的用例。切勿收集受到 GDPR 或 CCPA 保护的个人数据。
问:我需要代理吗?
不需要。住宅出口和地理路由内置于角色中 — 你发送查询,角色处理网络层和渲染。
问:tbm: "lcl" 有什么功能?
它选择 Google 的本地包 — 有地图支持的商业列表 — 而不是网页的 SERP。省略或更改它,角色将返回查询的有机网页结果。
问:会返回多少个地方?
角色返回 Google 为查询排名的卡片;捕获的 "旧金山的咖啡店" 查询返回 20 个。计数因查询、类别和地方而异。
问:如何定位不同的城市?
在 q 中放入地方。角色读取查询字符串,因此 旧金山的咖啡店 或 芝加哥的管道工 将返回该地区的本地包。
问:如果字段缺失,原始 HTML 在哪里?
metadata.rawUrl 存储渲染页面的副本。使用它来解析角色在解析对象中未显现的任何字段。
问:我可以在没有 AI 代理或 SDK 的情况下运行这个吗?
可以。这是纯 HTTP — curl、Python requests、Node fetch 或任何 HTTP 客户端都可以直接工作。无须 SDK。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



