mcpField
G
google-maps-scraper

google-maps-scraper

github.com/mahanaicoach营销与增长2.1k387 次安装2 周前更新
代码仓库

关于 google-maps-scraper

用于驱动本地 Google Maps Scraper 引擎,收集商家信息并整理潜在客户线索的技能。涵盖创建任务、获取结果,以及筛选实用联系字段。

主要功能

  1. 01创建并轮询异步抓取任务
  2. 02在单个任务中搜索多个关键词
  3. 03从商家网站提取电子邮件
  4. 04按需收集社交账号链接
  5. 05将所选字段导出为 CSV 或 JSON

适用场景

  1. 01整理本地商家潜在客户名单
  2. 02收集外联所需的联系信息
  3. 03通过网格搜索整个城市
  4. 04按需获取社交账号链接

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mahanaicoach/google-maps-scraper-kit --skill google-maps-scraper

安装后在 Claude Code 中输入/google-maps-scraper确认已加载。

详细介绍

Google Maps 抓取工具

通过调用本地引擎的任务 API,将业务类型和地点转换为整洁的潜在客户数据行。

基本概念

引擎(gosom/google-maps-scraper)作为本地 Docker 容器运行,并在 http://localhost:8080 提供 REST API。它没有身份验证,因此仅绑定到 localhost。抓取是一个异步任务: 创建任务,轮询直至完成,然后下载 CSV。一个任务可以运行多个关键词。每条结果最多包含 34 个原始字段。

步骤 0:检查引擎是否正在运行

curl -s http://localhost:8080/api/v1/jobs >/dev/null 2>&1 && echo UP || echo DOWN

如果状态为 DOWN:在套件根目录运行 docker compose up -d,等待约 10 秒后重试。如果未安装 Docker, 请引导用户查看 SETUP.md。

步骤 1:创建任务(POST /api/v1/jobs)

必填字段。缺少这些字段时,API 会返回 422:

  • keywords:搜索字符串数组。将地点写入每个搜索词:"plumbers in Denver CO"。
  • lat、lon:城市坐标,字符串格式:"39.7392"、"-104.9903"。
  • max_time:整数,单位为秒,即任务的最长运行时间,例如 300。API 内部会将其存储为纳秒, 但始终以秒为单位发送。

推荐字段:

  • depth(默认值为 10):滚动搜索的深度,大致决定每个关键词返回多少条商家信息。建议从 5 开始。
  • lang "en"、zoom 15(城市级别)、radius 10000(米)、fast_mode false。
  • email true:套件默认开启。 电子邮件是最有价值的潜在客户字段。引擎会访问每家商家的网站来查找 电子邮件地址,因此速度会稍慢一些。只有在明确需要快速运行且不需要电子邮件时,才设为 false。
curl -s -X POST http://localhost:8080/api/v1/jobs \
  -H "Content-Type: application/json" \
  -d '{"name":"job","keywords":["coffee shops in Austin TX"],"lang":"en","zoom":15,
       "lat":"30.2672","lon":"-97.7431","fast_mode":false,"radius":10000,
       "depth":5,"email":true,"max_time":300}'
# → {"id":"<uuid>"}   (HTTP 201; note: lowercase "id")

每次抓取都要处理以下两件事:

  1. 默认开启电子邮件(email:true)。只有用户想要快速运行时才关闭。
  2. 先询问社交资料。 创建任务前,先询问用户是否也需要 Instagram、Facebook 和 LinkedIn 个人资料 (参见下文“社交资料”)。绝不能默默跳过这个问题。

步骤 2:轮询直至完成(GET /api/v1/jobs/{id})

响应字段为 "Status"(S 大写)。其值会从 working 变为 ok(成功)或 failed。

运行环境规则: Bash 工具会阻塞前台 sleep。请将轮询循环作为 后台 Bash 命令运行(run_in_background: true),并在收到通知后读取其输出文件。 绝不要使用前台 sleep 进行轮询。

后台轮询代码片段。它会安全地解析值:匹配到结束引号为止,不要以 $ 作为锚点。

ID="<uuid>"
for i in $(seq 1 40); do
  S=$(curl -s "http://localhost:8080/api/v1/jobs/$ID" | grep -oE '"Status":"[^"]*"' | head -1 | cut -d'"' -f4)
  echo "status=$S"
  [ "$S" = ok ] && { echo DONE; break; }
  [ "$S" = failed ] && { echo FAILED; break; }
  sleep 15
done

步骤 3:下载并解析(GET /api/v1/jobs/{id}/download)

curl -s "http://localhost:8080/api/v1/jobs/$ID/download" -o results.csv

CSV 列(34):input_id, link, title, category, address, open_hours, popular_times, website, phone, plus_code, review_count, review_rating, reviews_per_rating, latitude, longitude, cid, status, descriptions, reviews_link, thumbnail, timezone, price_range, data_id, place_id, images, reservations, order_online, menu, owner, complete_address, about, user_reviews, user_reviews_extended, emails。

默认仅返回 8 个潜在客户字段

原始 CSV 有 34 列,其中大多数对拓展客户没有用处。默认情况下,仅返回 8 个潜在客户字段,也就是用于联系和评估潜在客户的数据,并删除其他所有内容:

title(名称)、phone、emails、website、category、address、review_rating、review_count

默认删除。 仅在用户明确要求时才展示以下字段:latitude/longitude(对客户拓展没有用处)、link、plus_code、cid、data_id、place_id、open_hours、popular_times、reviews_per_rating、reviews_link、thumbnail、images、timezone、price_range、status、input_id、complete_address、reservations、order_online、menu、owner、about、descriptions、user_reviews、user_reviews_extended。

scripts/scrape.py 已经只返回这 8 个潜在客户字段。使用 --full 保留所有列,或使用 --fields "a,b,c" 自选字段。默认会保存为 CSV 文件(results-<id>.csv);传入 --json 可输出 JSON。 如果直接调用 API,展示前请自行筛选出潜在客户字段。绝不要向用户输出完整的 34 列数据行。

社交资料:始终先询问用户(Instagram、Facebook、LinkedIn)

Google Maps 不提供社交链接,因此社交资料属于补充信息:访问每家商户的 website,并用正则表达式提取其 Instagram、Facebook 和 LinkedIn URL。抓取前,先询问用户是否也需要社交资料,只需询问一次,除非用户已经主动提出。如果需要,使用脚本:python3 scripts/scrape.py … --socials。

  • Token 成本。用户要求提取社交资料时,告知这一点:提取本身不消耗任何 LLM token,因为脚本使用的是普通 HTTP 请求和正则表达式。只有在将结果加载到聊天中时,才会给你的上下文增加每家商户约 40–50 个 token,例如,50 条潜在客户信息约增加 2k token。如果将文件保存在磁盘上并展示样例,这点开销可以忽略。保存文件并展示几行。
  • 不要自行通过 WebFetch 逐个抓取网站来查找社交资料。这样会将每个页面读入你的上下文,消耗数千个 token。脚本可免费完成这项工作,因此应始终优先使用 --socials。
  • 社交资料需要用户主动选择,且速度较慢(每家商户都要发起一次 HTTP 请求),覆盖率也不完整(约 40–70%)。只有在网站上链接了社交账号的商户才会有结果;没有网站的商户则不会有社交资料。如果用户预期能覆盖 100%,请说明这一点。

快捷方式。常见情况优先使用以下方式:

  • 单个关键词:scripts/scrape.sh "<keyword>" <lat> <lon> [depth](bash),一键创建任务、轮询并下载。
  • 自动地理编码(无需坐标):python3 scripts/scrape.py "<keyword>" --city "<City, ST>" [--depth N] 通过 OpenStreetMap Nominatim 获取纬度和经度。你也可以自行对城市进行地理编码,并传入坐标。 默认会提取电子邮件(使用 --no-email 跳过)。如果用户要求提取社交资料,添加 --socials。
  • 批量处理(多个关键词,一个任务):python3 scripts/scrape.py --keywords-file <file> --city "<City, ST>"。 API 接受 keywords 数组,因此应将所有词条放在同一个任务中,而不是发起多个任务。 仅在需要自定义任务请求正文(例如设置 proxies)时,才使用手动 curl 流程。

**整座城市范围的抓取:**用户说要抓取整座城市、所有商户或全市范围,或者一次抓取返回约 120 条结果(Google 的单次搜索上限)时,使用 python3 scripts/scrape.py "<keyword>" --city "<City, ST>" --grid 3。 它会将城市划分为 3 x 3 个区域(9 个任务),并根据 place_id 去重。各区域依次运行,因此网格抓取速度较慢,也更容易触发速率限制:提醒一次即可,不要因此阻止用户操作。

**深度电子邮件抓取:**只要启用了电子邮件提取,此功能就会默认开启。对于有网站但没有电子邮件的商户,会检查其联系页面和关于页面,脚本也会打印找到电子邮件的比例。使用 --no-deep-emails 可跳过此步骤。

其他端点

  • GET /api/v1/jobs 可列出任务。DELETE /api/v1/jobs/{id} 可删除任务并释放磁盘空间。
  • 浏览器 UI 和 OpenAPI 文档:http://localhost:8080 和 http://localhost:8080/api/docs。

最佳实践(摘自上游文档)

  • **抓取深度:**较高的 depth 会返回更多结果,但速度较慢,也更容易被拦截。从 5 开始,并按需提高。
  • **本地一次运行一个任务。**不使用代理时,同时运行多个任务会导致 Google 限流。
  • 电子邮件提取(email:true)会访问每家商户的网站,因此速度较慢。由于电子邮件是潜在客户信息中的关键字段,默认保持开启。如需快速抓取,可传入 --no-email(脚本)或 email:false(原始 API)。
  • **fast_mode:true**会返回精简数据,每个查询最多约 21 条结果,速度更快。适用于快速查询。
  • **代理:**对于大批量或重复运行的任务,可设置 "proxies"(包含 socks5://、http:// 或 https:// URL 的数组,支持身份验证)。引擎会轮换使用这些代理。这是防止触发速率限制的主要手段。
  • **zoom 和 radius**用于设置以 lat/lon 为中心的搜索范围。如果结果太少,可扩大 radius。
  • 扩展评论可用,但开销较大。只有用户要求获取评论文本时才启用。

速率限制、封锁和代理(执行大型任务前请阅读)

引擎会向 Google Maps 发送真实请求。上游项目唯一的正式说明是一则免责声明:

“请负责任地使用此抓取工具,并遵守适用的法律法规。未经授权的抓取可能违反服务条款。”

没有公开的封锁硬性阈值,因此请采取保守做法:

  • 如果抓取速度太快或数据量太大,Google 可能会暂时限制你的 IP 速率。限制会在几分钟到几小时内解除,不会影响用户的 Google 账号,但期间任务会失败。
  • 封锁迹象:任务返回 failed、结果为空或异常短,或与之前完全相同的运行相比,行数突然减少。发现这些迹象时,请降低频率(暂停、降低深度)或添加代理。
  • 并发与封锁(上游说明):“较高的并发……可能会增加封锁或失败的概率,尤其是在没有代理的情况下。首次运行请从默认值开始。” 参考吞吐量约为 -c 8 -depth 1 时每分钟 120 个地点。本地运行时,一次只运行一个任务,并从 depth 5 开始。

何时添加代理(上游说明:“对于较大的抓取任务,代理有助于避免速率限制”): 大型任务、多个关键词、重复或定时运行,或出现封锁迹象后。

  • 在任务请求正文中设置 "proxies" 数组。类型:socks5、socks5h、http、https。
  • 格式:protocol://user:pass@host:port(认证信息可选),例如 "proxies": ["socks5://user:pass@host:port", "http://host2:port2"]。引擎会自动轮换代理。

安全与防护措施

  • 警告,但不要阻止。 当请求规模较大(depth 较高、关键词较多、重复运行、使用网格,或设置了 email:true)时,继续执行,但首先输出一条简短警告,说明 IP 可能会被临时限制速率,并建议使用代理。正常的大型抓取任务不应被拦截、强制停止或要求确认。仅当用途明显具有滥用性或违法时(监视个人、发送垃圾信息、骚扰),才直接拒绝。
  • 除非使用认证代理,否则切勿将 API 暴露给 localhost 以外的地址。如果存在 API 密钥,切勿打印。
  • **个人数据:**抓取到的电子邮件和电话号码属于个人数据。如果用户要存储这些数据或联系相关人员,请提醒他们遵守 GDPR、CCPA 和 CAN-SPAM(合法依据、退订选项、禁止联系名单)。不要协助发送垃圾信息或进行骚扰。
  • **Google 的服务条款:**抓取 Google Maps 违反其服务条款。请控制抓取量,将输出视为有待核实的潜在客户信息,且不要转售原始 Google 数据。拒绝协助以监视个人为目的的用途。
  • **输出规范:**不要在聊天中倾倒大量 CSV 数据。将文件保存到磁盘,汇总数量并展示几行样例。存储前请按 place_id/cid 去重。
  • **磁盘:**结果会不断堆积在 Docker 卷中。请不时提议使用 DELETE 删除旧任务。

故障排除

  • 422 missing max time:添加 max_time(秒)。422 missing geo coordinates:添加字符串类型的 lat/lon。
  • 卡在 working:降低 depth、调高 max_time,或当前 IP 已被限流(添加代理或等待)。
  • CSV 为空:关键词范围太窄或坐标有误。扩大 radius 或修正坐标。
  • 连接被拒绝:容器已停止。运行 docker compose up -d。

评论

支持 Markdown