输入一个地点,Web Unlocker 就返回它的 Google 评论页面:评分、每个星级获得的评分数量、人们提到的主题,以及带正文的热门评论,按 1 页计费。页面加载失败不收费。
1,000 次免费请求 · 仅成功时计费 · 195+ 个国家和地区 · 适配 Claude
简单介绍一下您的团队,即可获得:
一个地点的 Google Maps 页面包含它的评分、每个星级的评分数量、人们提到的主题和热门评论,Web Unlocker 按 1 页计费。Google Places API 每次调用都计费,且只返回 5 条评论。评论采集工具则按每条评论计费。
再难的页面,
价格与普通页面相同。
页面加载失败不收费。您只为渲染成功的页面付费,没有其他费用。
1,000 个地点的 Google 评论的费用
1,000 个地点页面及其热门评论,按公布价格计算
Web Unlocker 的 Growth 套餐,每 1,000 个页面 $0.98。其他产品按这些页面上的 3,000 条评论计费,或按 1,000 次各含 5 条评论的调用计费。
官方 API 每个地点最多返回 5 条评论,且每次调用都计费。评论采集工具按每条评论计费。下面是各条路线完成同样 1,000 个地点所需的条件。
| 需要什么 | Google Places API | Apify | Outscraper | |
|---|---|---|---|---|
| 无需 Google API 密钥即可开始 | 是 | 否 | 是 | 是 |
| 您按什么付费 | 一页 | 每次调用 | 每条评论 | 每条评论 |
| 1,000 个含热门评论的地点 | $0.98 | $25 | $1.80 | $9 |
| 按星级拆分的评分,5 星到 1 星 | 是 | 否,仅有平均分 | 否 | 是 |
| 带数量的评论主题 | 是 | 否 | 否 | 否 |
| 整个页面的 HTML 或 Markdown | 是 | 否 | 否 | 否 |
要采集的不只是 Google 评论?Web Unlocker 以同样的方式、同样的价格返回任何页面。
Web Unlocker 本身没有提醒功能。您的脚本每天打开一次每个地点的页面:评分或评论数一有变化,就有新评论可读。1,000 个地点每天合计 $0.98。
评论监控工具每个地点每月 $65 起。
您自己的一次检查只需 $0.001。
每个地点一个请求:发送地点的 Google Maps 地址,取回渲染后的页面,读取评分、各星级数量、主题和评论。上面的演示运行的是同一个解析器。
填写上面的表单。密钥会在一个工作日内通过邮件送达。
google.com/maps/search/ 加上地点和所在城市,以及要从哪个国家打开。
页面包含评分、每个星级的数量、带数量的主题和热门评论,每条评论都有作者、星级、日期和正文。
pip install requestsGOLOGIN_SCRAPING_API_KEY=your_key python google_reviews.pyhttps://parsing.webunlocker.gologin.com/v1/scrapeimport json
import os
import re
import time
from urllib.parse import quote_plus
import requests
place = "Franklin Barbecue Austin"
address = f"https://www.google.com/maps/search/{quote_plus(place)}?hl=en&ucbcb=1"
html = ""
for attempt in range(3):
response = requests.get(
"https://parsing.webunlocker.gologin.com/v1/scrape",
headers={"apikey": os.environ["GOLOGIN_SCRAPING_API_KEY"]},
params={
"url": address if attempt == 0 else f"{address}&_r={int(time.time())}",
"render_js": "true",
"wait": "9000",
"geo": "us",
"format": "json",
},
timeout=120,
)
html = response.json().get("data", {}).get("html", "")
if 'data-review-id="' in html:
break
def first(pattern):
match = re.search(pattern, html)
return match.group(1) if match else None
blocks = {}
for match in re.finditer(r'data-review-id="([^"]+)"', html):
blocks.setdefault(match.group(1), match.start())
starts = sorted(blocks.values()) + [len(html)]
reviews = []
for start, end in zip(starts, starts[1:]):
block = html[start:end]
author = re.search(r'class="d4r55[^"]*"[^>]*>([^<]+)<', block)
text = re.search(r'class="wiI7pd"[^>]*>([^<]*)<', block)
if author and text:
stars = re.search(r'aria-label="(\d) stars?"', block)
date = re.search(r'class="rsqaWe"[^>]*>([^<]+)<', block)
reviews.append({
"author": author.group(1),
"stars": int(stars.group(1)) if stars else None,
"date": date.group(1) if date else None,
"text": text.group(1),
})
print(json.dumps({
"name": first(r"<h1[^>]*>([^<]+)"),
"rating": first(r'class="F7nice[^"]*"[^>]*>\s*<span><span aria-hidden="true">([\d.]+)<'),
"ratings": first(r'aria-label="([\d,]+) reviews?">\('),
"stars": {level: first(rf'aria-label="{level} stars?, ([\d,]+) reviews?"') for level in "54321"},
"topics": dict(re.findall(r'aria-label="([^",]+), mentioned in ([\d,]+) reviews?"', html)),
"reviews": reviews,
}, indent=2, ensure_ascii=False))GOLOGIN_SCRAPING_API_KEY=your_key node reviews-batch.mjshttps://parsing.webunlocker.gologin.com/v1/scrapeconst places = [
'Franklin Barbecue Austin',
'Katz Delicatessen New York',
'Relax and Smile Dental Care Miami',
];
const number = (text) => (text ? Number(text.replace(/,/g, '')) : null);
async function pageOf(place, attempt) {
const address = `https://www.google.com/maps/search/${encodeURIComponent(place).replace(/%20/g, '+')}?hl=en&ucbcb=1`;
const params = new URLSearchParams({
url: attempt === 1 ? address : `${address}&_r=${Date.now()}`,
render_js: 'true',
wait: '9000',
geo: 'us',
format: 'json',
});
const response = await fetch(`https://parsing.webunlocker.gologin.com/v1/scrape?${params}`, {
headers: { apikey: process.env.GOLOGIN_SCRAPING_API_KEY },
});
return (await response.json()).data?.html ?? '';
}
async function reviewsOf(place) {
let html = '';
for (let attempt = 1; attempt <= 3 && !html.includes('data-review-id='); attempt += 1) {
html = await pageOf(place, attempt);
}
const star = (level) => number(html.match(new RegExp(`aria-label="${level} stars?, ([\\d,]+) reviews?"`))?.[1]);
return {
place: html.match(/<h1[^>]*>([^<]+)/)?.[1] ?? place,
rating: number(html.match(/class="F7nice[^"]*"[^>]*>\s*<span><span aria-hidden="true">([\d.]+)</)?.[1]),
ratings: number(html.match(/aria-label="([\d,]+) reviews?">\(/)?.[1]),
fiveStar: star(5),
oneStar: star(1),
topReview: html.match(/class="wiI7pd"[^>]*>([^<]{0,80})/)?.[1],
};
}
const rows = [];
for (const place of places) rows.push(await reviewsOf(place));
console.table(rows);GOLOGIN_SCRAPING_API_KEY=your_key node reviews-watch.mjshttps://parsing.webunlocker.gologin.com/v1/scrapeimport { readFile, writeFile } from 'node:fs/promises';
const places = ['Franklin Barbecue Austin', 'Katz Delicatessen New York', 'Relax and Smile Dental Care Miami'];
const FILE = 'reviews.json';
const number = (text) => (text ? Number(text.replace(/,/g, '')) : null);
async function pageOf(place, attempt) {
const address = `https://www.google.com/maps/search/${encodeURIComponent(place).replace(/%20/g, '+')}?hl=en&ucbcb=1`;
const params = new URLSearchParams({
url: attempt === 1 ? address : `${address}&_r=${Date.now()}`,
render_js: 'true',
wait: '9000',
geo: 'us',
format: 'json',
});
const response = await fetch(`https://parsing.webunlocker.gologin.com/v1/scrape?${params}`, {
headers: { apikey: process.env.GOLOGIN_SCRAPING_API_KEY },
});
return (await response.json()).data?.html ?? '';
}
async function countOf(place) {
let html = '';
for (let attempt = 1; attempt <= 3 && !html.includes('data-review-id='); attempt += 1) {
html = await pageOf(place, attempt);
}
return {
rating: number(html.match(/class="F7nice[^"]*"[^>]*>\s*<span><span aria-hidden="true">([\d.]+)</)?.[1]),
ratings: number(html.match(/aria-label="([\d,]+) reviews?">\(/)?.[1]),
};
}
const before = JSON.parse(await readFile(FILE, 'utf8').catch(() => '{}'));
const today = { ...before };
for (const place of places) {
const now = await countOf(place);
const was = before[place]?.ratings ?? null;
if (now.ratings === null) console.log(`${place}: no page today, ask again`);
else if (was === null) console.log(`${place}: first check, ${now.ratings} ratings, ${now.rating} stars`);
else if (now.ratings > was) console.log(`${place}: ${now.ratings - was} new, now ${now.ratings} ratings, ${now.rating} stars`);
else console.log(`${place}: nothing new`);
if (now.ratings !== null) today[place] = now;
}
await writeFile(FILE, JSON.stringify(today, null, 2));需要先找到这些地点?Google Maps 爬虫会列出某个城市里某一类别的全部地点,每个地点在这里再多一页。
一个账户,一个代理网络,一套生态。按任务需要选择产品。
还要采集地点本身?请查看 Google Maps 爬虫、Reddit 和 YouTube 采集工具,或全部网页采集工具。
把地点的 Google Maps 地址发送给 Web Unlocker:google.com/maps/search/ 加上名称和城市。它会在您选定的国家用真实浏览器打开页面,并连同评分、每个星级的评分数量、人们提到的主题和热门评论一起返回,每条评论都有作者、星级、日期和正文。上面的代码正是这样做的。
用 requests 库把地点地址发送给 Web Unlocker,再从页面中读取各个字段。上面的 Python 标签页是一份完整的脚本,已在真实 API 上测试过。
能。地点的 Google Maps 页面是公开的,无需登录即可加载。Web Unlocker 像访客的浏览器一样看到它并返回,不需要 Google Cloud 项目,不需要 API 密钥,也不需要审批。
官方有两个。Google Places API 返回地点的评分和最多 5 条评论,每 1,000 次调用 $25。Google Business Profile API 返回全部评论,免费,但仅限您拥有或管理的地点。要获取其他地点超出这 5 条的评论,并带有星级分布,Web Unlocker 返回的是 Maps 页面本身。
这是它文档中写明的上限:Place Details 每个地点最多返回 5 条评论,按相关性排序,对应的 SKU 每 1,000 次调用 $25。它只给出平均评分,没有星级分布。Maps 页面包含每个星级的数量和评论主题,Web Unlocker 返回整个页面。
返回带完整正文的前 3 条评论,以及评分、每个星级的数量和带数量的主题。自 2026 年 9 月起,Google Maps 只有在登录后才显示地点的完整评论列表,所以所有读取公开页面的工具拿到的都是这些。对于您自己的地点,Google Business Profile API 可免费列出每一条评论。
从公开页面不行:Google 把完整列表和排序选项放在登录之后。保持公开的是摘要和热门评论,它们按一页的价格一次返回。
排序同样在登录之后。页面包含的是热门评论。要发现新评论,请把评论数和评分与上一次运行比较:上面的“每日检查”标签页就是对一组地点这样做的。
会:每个地点每个星级获得的评分数量,5 星到 1 星。我们测试当天奥斯汀的 Franklin Barbecue:5 星 6,053 个,4 星 695 个,3 星 285 个,2 星 104 个,1 星 199 个。
能,分两步。Google Maps 爬虫按区块列出某一类别的地点,然后每个地点在这里再多一页。迈阿密的 146 家牙医来自 25 个搜索页,它们的 146 个评论页合计 171 页,总共约 17 美分。
如果您拥有或管理该商家信息,请使用 Google Business Profile API:Google 批准您的项目后,它可免费列出您各个地点的每一条评论,每页 50 条。Web Unlocker 适用于您不管理的地点。
Web Unlocker 返回的是页面,而不是表格,所以在您看到之前不会丢失任何内容。把它转成 CSV 只需几行代码,或者一句提示词:用 Gologin scraping skill 把页面交给 Claude,让它输出 CSV。
每 1,000 个页面低于 $1,每个页面价格相同:1,000 个含评论的地点只需 $0.98。页面加载失败不收费。套餐每月 $49 起,含 50,000 次请求。
有,可以免费开始:Web Unlocker 附带 1,000 次免费请求,足够采集 1,000 个地点及其评论。
不需要。Web Unlocker 会为您选择 IP,覆盖 195+ 个国家和地区,并从您选择的国家打开页面。
这取决于您的需求。Apify 和 Outscraper 出售整理好的现成数据行,并按每条评论计费。Web Unlocker 以每页一个价格返回完整的 Maps 页面,带有这些数据行没有的星级分布和主题,解析方式由您决定。
地点的 Maps 页面是公开的,无需登录即可加载。Web Unlocker 像访客的浏览器一样加载它并返回页面。您采集什么、如何使用,由您自己决定,请对照适用于您项目的规则自行核对。
简单介绍一下您的团队,即可获得: