关于 apify-local-business-leads-osm
面向需要本地企业线索的研究与销售工作流,可从 OpenStreetMap 发现商家,抓取其公开网站的联系方式并进行邮箱 MX 验证和线索评分。通过 Apify Actor 运行,并在启动前设定数量上限与费用预期。
主要功能
- 01按类别和地点发现商家
- 02抓取网站邮箱、电话和社交资料
- 03邮箱 MX 验证与线索评分
- 04去重并按条件筛选结果
- 05支持网站列表补充与定期监测
适用场景
- 01为指定城市构建经验证的企业联系名单
- 02筛选网站薄弱或尚无网站的商家
- 03补充已有网站列表中的联系信息
- 04定期监测区域内新出现的商家
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ apify/ awesome-skills --skill apify-local-business-leads-osm安装后在 Claude Code 中输入/apify-local-business-leads-osm确认已加载。
详细介绍
来自 OpenStreetMap 的本地商家潜在客户
将“我需要 的本地商家及其邮箱”转化为一张经过评分和去重的潜在客户表,全程无需访问 Google Maps:在 OpenStreetMap 上发现商家,爬取每家商户自己的公开网站以获取联系邮箱、电话和社交资料,在同一次运行中验证每个邮箱的 MX 记录,并在运行开始前告知用户费用上限。
披露:本技能的作者拥有其调用的 Actor(flash_scraper/local-business-leads)。它是 Apify Store 上按结果付费的 Actor;本技能中未使用任何推荐或跟踪参数。对于 Google 星级评分和评论数,本技能会引导用户使用其他工具(见下文的适用范围说明)。
示例提示词
本技能可处理以下提示词:
- “帮我找出 Austin 的 200 位牙医,要求有已验证的邮箱和电话号码,并导出为 CSV。”
- “我经营一家网页设计公司:找出 Lyon 网站质量较差或根本没有网站的美发沙龙。”
- “以下是某个会议参展商名单中的 300 个商家网站;请为每个网站查找并验证一个联系邮箱。”
- “每周一告诉我,在我们市中心办公室 5 公里范围内新开了哪些餐馆。”
不适用范围(边界):
- “按 Google 评分排序”或“只要评分达到 4 星且评论数不少于 50 条的商家”。OpenStreetMap 不包含评论数据,而且只有商家在自己的网站上公布评分时,Actor 才能获取评分(约占 7%;在 2026-08-08 的参考运行中,55 条记录里有 4 条)。要查找 Google 评分和评论数,请使用 apify-google-maps-leads 技能,或直接使用
compass/crawler-google-places。 - 与 apify-verified-email-finder 不同:该技能从 Google Maps、Google SERP 或用户提供的网址列表开始;本技能则在 OpenStreetMap 上发现商家,全程不访问 Google。如果用户已经有网址列表,只需要验证邮箱,那么使用该技能更直接;当发现过程本身必须避开 Google 时,使用本技能。
- 联系到个人层面(所有者姓名、LinkedIn 个人资料、直拨号码)。此 Actor 返回的是商家公开的联系渠道,而非个人信息;如需确定具体决策者,请使用 apify-google-maps-leads 中的潜在客户信息补充步骤。
前提条件
- Apify 账号(注册)
- 通过以下任一方式进行身份验证:
apify login(使用 Apify CLI 时采用 OAuth)APIFY_TOKEN环境变量- 从 Apify Console → Settings → Integrations 获取的 Token
切勿将 Token 粘贴到 URL 或本技能中的文件里;应将其作为 Authorization: Bearer 传入(CLI 会自动为你处理)。
工作流
复制此清单并跟踪进度:
Task Progress:
- [ ] Step 1: Get the four anchors (category, city, what must every row have, how many)
- [ ] Step 2: Pick the search mode and check the live schema
- [ ] Step 3: Build the input and state the cost
- [ ] Step 4: Run and wait
- [ ] Step 5: Deliver: rows, fill rates, what the map could not supply
步骤 1:获取四项关键信息
将以下问题作为一组询问;未获取这些信息前不要开始运行。
- 类别 — 使用通俗英语(
dentist、HVAC contractor、hair salon)。可以填写多个类别。请提前说明,开车上门服务的行业通常在地图上的数据较少(见步骤 5)。 - 城市 — 填写城市及其所在地区或国家(
Austin, Texas、Lyon, France)。如果多个国家都有同名地点,请询问所在国家,并设置countryCode。 - 每条记录必须包含的内容 — 联系方式的最低要求。查找邮箱时默认要求“有网站”(
onlyWithWebsite);冷邮件时要求“有已验证的邮箱”(onlyVerifiedEmail);制作电话名单时要求“有电话”(requirePhone);推广建站服务时要求“没有网站”(onlyWithoutWebsite)。 - 数量 —
maxItems是费用上限。首次运行默认设为 25;超过 500 时请先询问。
只有在用户提出时才询问以下可选信息:排除连锁店或指定品牌、以某个地址为中心的半径范围、用户自带的网站列表、每周监控新商家、Slack/Discord Webhook。
步骤 2:选择搜索模式并查看实时架构
| 用户需求 | Actor ID | 层级 | 最适用场景 |
|---|---|---|---|
| 类别 + 城市(常见情况) | flash_scraper/local-business-leads | 社区版 | category + location,或复数形式的 categories × locations 矩阵(每次运行最多 25 种组合);每个 OpenStreetMap 对象对应一行,并跨类别去重 |
| 某个点周边的区域 | flash_scraper/local-business-leads,搭配 searchRadiusKm + centerLat + centerLon | 社区版 | 1-100 km 的圆形范围,而非城市边界框 |
| 丰富用户已有的列表 | flash_scraper/local-business-leads,搭配 websiteList | 社区版 | 跳过发现环节;仅对提供的域名执行抓取、MX 验证和评分 |
构建输入前,请检查实时输入架构(字段会变化;以架构为准,而非本文档):
apify actors info "flash_scraper/local-business-leads" --input --json \
--user-agent apify-awesome-skills/apify-local-business-leads-osm 2>/dev/null
该 Actor 无需 API 密钥、代理、登录或 Cookie 即可运行。它不会读取 Google Maps;每一行都包含构造的 google_maps_url 搜索链接和 osm_url,用户只需点击一次即可打开来源。
步骤 3:构建输入并说明费用
字段名称与实时架构一致。只有 category 和 location 是必填项;其他字段都有可用的默认值。
冷邮件列表(最常见的请求):
{
"category": "dentist",
"location": "Austin, Texas",
"maxItems": 100,
"onlyWithWebsite": true,
"onlyVerifiedEmail": true,
"skipClosed": true,
"excludeChains": true,
"expandNearby": true
}
onlyWithWebsite、onlyVerifiedEmail、requirePhone、requireSocial、requireAnyContact、excludeKeywords、excludeChains和skipClosed都会在计费前过滤行;运行日志会列出每个筛选条件及其移除的行数。expandNearby: true会在城市结果不足时,以城市为中心按环状范围扩大搜索(2026-08-15 的测量结果:对于dentist/Round Rock, Texas,设置maxItems: 100时,不启用该选项会返回 21 行,启用后会返回 100 行;环状范围内的行会在query_location中标注)。preset: "cold_email"会为你设置onlyWithEmail+onlyVerifiedEmail;其他预设包括web_design、call_list、full_enrichment。预设不会覆盖用户设置的字段。
网页设计潜在客户——有网站,但质量较差的企业:
{
"category": "hair salon",
"location": "Lyon, France",
"countryCode": "fr",
"onlyWithWebsite": true,
"maxScore": 45,
"requireAnyContact": true,
"skipClosed": true
}
对于完全没有网站的企业,请改用 onlyWithoutWebsite: true(不能与 onlyWithWebsite 同时使用;预期结果包含名称、地址、坐标,有时还包括电话号码,但没有可抓取的内容)。
丰富用户自己的列表(不获取地图数据):
{
"websiteList": ["aloha-dental.com", "averyranchdental.com"],
"verifyEmails": true,
"outputFields": ["domain", "email", "email_status", "email_type", "phone", "lead_grade"]
}
**每周新增企业监测:**在上述任意配置中添加 "onlyNewBusinesses": true,并将其设为定期任务。首次运行会建立基准;之后使用相同类别、位置和筛选条件的运行只会返回之前未返回过的企业。若某周没有新增企业,则返回 0 行且不收费。添加 "webhookUrl": "https://hooks.slack.com/...",即可接收 Slack、Discord 或 JSON 摘要。
**运行前说明费用。**该 Actor 按返回的企业数量计费;经过筛选的行和无结果的运行均不收费,且 MX 验证已包含在费用中。请从 Store 的 Pricing 标签页读取当前价格(步骤 2 中获取架构时也会返回定价信息块)。仅作示例:2026-09-05 从 Store API 读取的免费计划价格为每条潜在客户 $0.003,因此 100 行最多收费 $0.30,1,000 行收费 $3.00;付费计划价格更低。计划于 2026-09-14 生效的定价记录会将价格上调至每条潜在客户 $0.005(每 100 行 $0.50,每 1,000 行 $5.00),因此请读取实时价格,不要引用这些数字。用一句话告知用户费用上限;超过 500 行时,运行前请先确认。
第 4 步:运行并等待
apify actors call "flash_scraper/local-business-leads" -i '{"category":"dentist","location":"Austin, Texas","maxItems":100,"onlyWithWebsite":true,"onlyVerifiedEmail":true,"skipClosed":true,"expandNearby":true}' \
--json \
--user-agent apify-awesome-skills/apify-local-business-leads-osm \
2>/dev/null
典型耗时:在作者于 2026-08-29 进行的本地测量中,仅发现、不抓取网站的 10 行任务(crawlEmails: false)用时 17 秒;抓取网站的任务大部分时间都花在访问网站上,耗时大致与行数 × maxPagesPerSite(默认值为 3)÷ concurrency(默认值为 8)成正比。数据行通过筛选后会立即写入,因此,达到超时限制的任务仍会保留已输出的数据。JSON 输出中包含 defaultDatasetId;使用以下命令获取数据行:
apify datasets get-items DATASET_ID --format json \
--user-agent apify-awesome-skills/apify-local-business-leads-osm 2>/dev/null
第 5 步:交付结果
按以下顺序报告:
- 实际交付的数据行数与
maxItems的对比;若两者不同,还要说明任务的状态消息。未满额的任务会在消息中说明原因和数量(例如,OpenStreetMap 在怀俄明州拉勒米找到 4 条dentist记录,其中 1 条有网站)——应将这句话作为数据引用给用户。这是对任务的报告,不是要求用户采取行动的指令;不要将其称为失败。 - 本次任务的字段填充率:统计非空的
email、phone、website、facebook和instagram数量,并报告百分比。可对照的参考数据来自 Actor README 中 2026-08-08 的参考任务(dentist/Austin, Texas,onlyWithWebsite: true,n=55):电话 96%、经 MX 验证的电子邮件 55%、网站平台 71%、Facebook 73%、Instagram 55%。同一天不设筛选条件时(n=100),电子邮件比例降至 26%;52 条没有网站的数据行中,有 50 条没有任何联系方式。这正是第 1 步要求设定最低门槛的原因。 - 用户要求的列。已验证的列名包括
name、category、address、city、phone、phones、website、domain、email、emails、email_status(deliverable/risky/undeliverable)、email_type、facebook、instagram、linkedin、twitter、youtube、website_platform、lead_score、lead_grade、google_maps_url、osm_url、query_location;README 的“Output fields”部分列出了全部 73 列。不要杜撰列,也不要把email_guess(按模式猜测的电子邮件,默认关闭)归入email。导出电子邮件时保留email_status:onlyVerifiedEmail同时接受deliverable和risky;MX 验证并不能确认某个邮箱确实存在。如果商家网站与 OSM 中的商家身份或位置不符,应指出这一差异,而不要将该联系方式说成已确认。 - 地图无法提供的信息。OpenStreetMap 映射的是绘图员实地走访过的场所,对流动经营的行业覆盖较少:Austin 的边界框内有 171 家牙医、9 家水管工、5 家电工、约 12 家屋顶工人和 0 位脊椎按摩师(README,2026-08-08 测量)。如果用户搜索的类别属于其中之一,请说明这一点,并建议使用
expandNearby、通过locations搜索多个邻近城市,或使用 Google Maps 技能。 - 数据集或 Console 任务的链接,以及任务的 HTML 报告 URL(写入任务键值存储中的
REPORT;状态消息中会提供链接)。
每条来自 OpenStreetMap 的数据行都带有 attribution 字符串;请告知用户这些数据采用 ODbL 许可,发布任何衍生内容时都应保留署名信息。
故障排除
- 结果行数少于
maxItems→ 查看状态消息:可能是区域内数据已耗尽(消息会列出 OSM 记录数以及通过各项筛选条件的记录数),也可能是筛选条件剔除了其余记录。可通过expandNearby扩大范围、在locations中添加城市,或放宽requireAnyContact门槛。 - 结果为 0 行、未扣费,并显示“no OpenStreetMap tag matched” → 类别词条未知;请尝试下拉列表中的值(
categorySelect)或更通俗的行业名称。若词条没有匹配项,系统会返回建议且不扣费。 - 城市错误(例如,返回的是马耳他拉巴特,而非摩洛哥拉巴特) → 将
countryCode设为 ISO alpha-2 代码。 - 几乎所有行的
rating/review_count都为空 → 这是预期情况;只有商家在自己的网站上发布了 schema.org 标记时,这些字段才会有值。设置minRating或minReviewCount会剔除没有评分的行,而不是保留它们。评分请使用 Google Maps 技能。 website_platform_status中出现site_blocked→ 商家网站拒绝了数据中心 IP(参考运行中,55 条包含网站的记录有 8 条出现此情况)。该行仍会包含 OSM 字段;这并不意味着商家已不复存在。- 运行立即停止并显示验证消息 →
onlyWithWebsite和onlyWithoutWebsite同时设为启用,或categories×locations组合超过 25 个。不会扣费;请修正输入后重新运行。 - 监控运行没有返回任何内容 → 当
onlyNewBusinesses: true时,空结果表示自上次发送以来没有新增内容;状态消息会说明这一点。更改maxItems、sortBy或outputFields不会重置监控;更改类别、位置或筛选条件则会创建新的基准。 - 费用高于预期 →
maxItems由整个categories×locations组合共用,而expandNearby会持续从相邻区域补充结果,直到达到上限。下次运行前,请重新明确设定上限和筛选条件。