开源AI代理自动挖掘B2B销售线索:架构拆解与实战

📅 2026/8/27 7:30:35
开源AI代理自动挖掘B2B销售线索:架构拆解与实战
最近在看 GitHub 趋势榜单时发现“AI 代理 B2B 销售线索挖掘”这类开源项目热度涨得非常快。它的核心思路很简单不再让人工一个个去搜公司官网、找联系人邮箱、判断客户意向而是让一个 AI 代理自动完成“找线索—补全信息—筛选评分—输出名单”的完整链路。过去要做一套这样的系统通常需要自己维护爬虫、对接搜索 API、准备一堆数据清洗脚本。而现在的开源项目把很多环节标准化了比如线索来源管理、LLM 信息抽取、数据去重、CRM 接口对接等都可以直接用现成模块组合起来。本文将围绕“开源 AI 代理自动找 B2B 潜客”这个主题拆解这类项目的核心架构并提供一个可以本地运行的最小实战示例。内容定位不是纯概念科普而是偏工程落地会讲清楚每个模块在做什么、为什么需要它、以及实际使用中容易踩的坑。适合正在做销售自动化、开发者工具、SaaS 增长相关方向的同学参考。1. 为什么需要“AI 代理”来找 B2B 潜客1.1 传统 B2B 获客方式的痛点B2B 销售和 To C 增长不同客户决策周期长、客单价高、目标人群集中所以“找到对的联系人”比“触达更多人”更重要。传统的找线索方式通常是这样销售或市场人员手动在搜索引擎搜“XX 行业 公司 官网”。打开公司官网找“关于我们”“团队介绍”“联系方式”等页面。用各种工具猜测联系人邮箱比如firstname.lastnamecompany.com。手动整理到 Excel 表格再逐个验证邮箱是否有效。最后才开始发开发信。这个过程非常耗时。假设要整理 100 家目标公司每家需要 10 分钟那就是接近 17 个小时的纯重复劳动。而且人工操作很容易漏掉关键信息比如公司近期融资、招聘扩张、官网改版等“购买信号”很难被系统化记录。1.2 开源 AI 代理解决了什么问题开源 AI 代理不是简单地把“手动搜索”变成“自动搜索”而是把整个销售线索挖掘流程重构成一条自动化流水线传统流程AI 代理流程人工搜索目标公司自动从多源聚合线索手动浏览官网找信息抓取页面后用 LLM 抽取结构化数据猜测并验证邮箱调用验证 API 或 MX 记录检查凭经验判断客户意向基于购买信号打分排序录入 Excel / CRM自动写入数据库或推送 CRM对比下来核心价值不只是“省时间”而是让线索数据更完整、筛选标准更一致、更新频率更高。1.3 和普通爬虫的区别很多人会觉得这事写个爬虫不就行了其实区别很大。爬虫解决的是“把网页内容抓下来”而 AI 销售线索代理解决的是“从杂乱信息中判断谁是潜在客户并生成可执行的联系人名单”。它至少需要具备三方面能力搜索能力知道去哪里找潜在客户比如招聘网站、行业目录、开源社区、新闻公告。理解能力能读懂网页内容知道“这家公司在招聘销售总监”意味着公司可能在扩张也可能是销售团队不成熟。行动能力能调用邮箱验证服务、CRM API、日历工具把线索推进到下一步。所以这类项目通常不是单个爬虫脚本而是一个多模块协作系统。2. 开源 B2B 潜客代理的核心架构2.1 典型流水线从 GitHub 上的主流项目来看这类 AI 代理的架构大多可以归纳为五个阶段线索获取 - 信息补全 - 质量评分 - 验证去重 - 输出与推送每个阶段对应不同的职责线索获取从搜索引擎、行业站点、招聘信息、社交媒体等渠道找到候选公司。信息补全抓取候选公司官网收集业务描述、员工规模、技术栈、关键联系人信息。质量评分根据预设规则或 LLM 判断候选公司是否符合“目标客户画像”。验证去重校验邮箱格式、域名 MX 记录、邮箱是否有效同时去除重复数据。输出与推送将最终结果写入 CSV、Google Sheets、数据库或 CRM 系统。2.2 核心模块拆解2.2.1 线索来源模块这个模块决定“代理从哪里找客户”。常见来源包括搜索引擎结果页通过 SerpAPI、Bing Search API 或自建 SearXNG 实例。招聘信息例如公司发布招聘说明业务扩张。技术社区和 GitHub例如某个开源项目的使用者可能就是潜在客户。企业公开数据库工商信息、融资事件等。在设计上来源应该做成可插拔的。不同行业、不同目标客户可能适合不同来源。比如做开发者工具的公司从 GitHub 生态找线索会比从工商数据库更有效。2.2.2 抓取与解析模块找到候选网站后代理需要抓取页面内容。这个模块有两个技术路线一是基于requestsBeautifulSoup的轻量方案适合页面结构相对固定的官网。优点是简单、快缺点是对动态渲染页面无效。二是基于 Playwright 的浏览器自动化方案可以执行 JavaScript拿到完整的渲染后页面。适合官网大量使用前端框架的场景但资源消耗更高。抓取之后HTML 需要转成纯文本或 Markdown方便后续交给 LLM 处理。这一步可以统一用trafilatura或readability-lxml这类正文提取库。2.2.3 LLM 信息抽取模块这是“AI 代理”最核心的部分。抓到页面后需要用 LLM 将非结构化文本转换成结构化字段例如{ company_name: 示例科技有限公司, industry: 企业软件, employees: 50-100, technologies: [Next.js, PostgreSQL, AWS], hiring_tags: 正在招聘销售经理, contact_email: contactexample.com, summary: 为中小企业提供 CRM 解决方案 }这里不需要训练模型而是用提示词工程指导 LLM 输出指定格式。为了保证输出稳定可以采用JSON Schema约束或函数调用Function Calling机制。2.2.4 评分与筛选模块拿到结构化信息后系统需要判断“这个公司值不值得跟进”。评分规则通常分两层硬性条件行业是否匹配、公司规模是否在范围内、所在地区是否符合目标市场。软性信号是否正在招聘相关岗位、最近是否有融资、技术栈是否与产品互补。使用开源模型时本地部署的优点是数据不出内网。文件、客户名单、竞品信息更适合用本地化方案。2.3 常用技术选型模块推荐方案说明搜索接口SearXNG / Bing Search APISearXNG 可自托管无搜索额度限制浏览器抓取Playwright适合动态页面正文提取trafilatura从 HTML 提取正文效果较好LLM 调用OpenAI 兼容接口 / Ollama支持本地模型方便隐私保护数据存储SQLite / PostgreSQL轻量可用 SQLite多机协作用 PostgreSQL任务调度Cron / APScheduler定期扫描线索源推送集成CRM API / Webhook / 邮件按实际业务系统扩展3. 环境准备与项目结构3.1 运行环境本文的实战示例基于 Python 3.10依赖管理使用pip。如果你的项目已经用了 Poetry 或 uv也可以对应调整重点理解代码逻辑即可。操作系统Windows / macOS / Linux 均可。Python 版本3.10 或以上。LLM 服务本地 Ollama或任意 OpenAI 兼容接口模型名称按实际部署调整。Python 包requests、beautifulsoup4、trafilatura、openai、pydantic。3.2 项目目录结构b2b-lead-agent/ ├── config/ │ └── settings.yaml ├── agents/ │ ├── sourcing.py │ ├── extractor.py │ └── scorer.py ├── storage/ │ └── db.py ├── data/ │ └── leads.json ├── requirements.txt └── main.py这个结构不复杂但方便后续扩展。如果项目变大建议再把每个模块拆成独立服务。3.3 依赖安装创建虚拟环境并安装依赖python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate pip install requests beautifulsoup4 trafilatura openai pydantic这里openai库不仅支持 OpenAI 官方接口也兼容大部分本地推理服务因为本地服务通常也提供 OpenAI 风格的/v1/chat/completions端点。4. 最小可运行示例下面我们来实现一个简化版的 B2B 潜客代理。它做的事情是从一个行业关键词列表出发搜索潜在客户。访问候选公司官网抓取页面内容。用 LLM 抽取关键信息并判断是否匹配目标客户画像。去除重复数据输出 JSON 结果文件。4.1 定义搜索与抓取逻辑新建agents/sourcing.py实现候选网站收集与页面抓取# agents/sourcing.py import requests from bs4 import BeautifulSoup import trafilatura class SourcingAgent: 负责收集候选公司和抓取官网内容 def __init__(self, search_url_template: str): # 这里传入一个可用的搜索接口模板 # 示例中使用 Bing 搜索请按实际搜索服务调整参数 self.search_url_template search_url_template def find_candidates(self, keyword: str, limit: int 5) - list[str]: 根据关键词搜索候选公司官网 urls [] # 简化处理解析搜索结果中的外链 # 实际项目中建议使用正规搜索 API避免高频抓取搜索页面 resp requests.get( self.search_url_template.format(keywordkeyword), headers{User-Agent: Mozilla/5.0}, timeout10, ) soup BeautifulSoup(resp.text, html.parser) for a in soup.select(li b a): href a.get(href) if href and href.startswith(http): urls.append(href) if len(urls) limit: break return urls def fetch_content(self, url: str) - str: 抓取网页正文内容 downloaded trafilatura.fetch_url(url) if not downloaded: return return trafilatura.extract(downloaded)代码说明这个模块负责两件事第一是获取候选页面链接第二是抓取页面正文。trafilatura的作用是剔除导航、页脚、广告等噪声只保留文章主体。在正式项目中搜索部分建议改为调用搜索引擎官方 API避免给搜索结果页造成压力。4.2 用 LLM 抽取字段新建agents/extractor.py负责调用 LLM 识别企业信息# agents/extractor.py import json from openai import OpenAI class ExtractorAgent: 用 LLM 从页面文本中抽取结构化企业信息 def __init__(self, base_url: str, api_key: str, model: str): self.client OpenAI(base_urlbase_url, api_keyapi_key) self.model model def extract_company_info(self, text: str) - dict: prompt f 你是一个 B2B 销售线索分析助手。 请从以下网页正文中抽取企业信息并输出 JSON。 字段要求 - company_name: 公司名称 - industry: 所属行业 - employees: 员工规模未知则为 null - sell_to: 这家公司的目标客户类型 - contact_email: 页面上能找到的邮箱 - summary: 一句话业务介绍 网页正文 {text[:3000]} 只输出 JSON不要输出解释。 try: resp self.client.chat.completions.create( modelself.model, messages[ {role: system, content: 你是信息抽取助手只输出 JSON。}, {role: user, content: prompt}, ], temperature0, ) content resp.choices[0].message.content # 兼容 json ... 包裹的情况 if in content: content content.split()[1] if content.startswith(json): content content[4:] return json.loads(content) except Exception as e: print(f[extractor] 解析失败: {e}) return {}这里的关键点是温度设为 0让模型输出尽量稳定同时用 JSON 格式约束输出方便后续程序处理。如果你用的是不同格式的本地模型可能需要对提示词做微调。4.3 定义线索评分逻辑新建agents/scorer.py对候选公司进行过滤与评分# agents/scorer.py class LeadScorer: 根据目标客户画像过滤和评分 def __init__(self, include_industries: list[str], min_employees: int 10): self.include_industries [x.lower() for x in include_industries] self.min_employees min_employees def score(self, company: dict) - dict: 返回带 score 字段的线索记录 score 0 reasons [] industry (company.get(industry) or ).lower() if any(tag in industry for tag in self.include_industries): score 30 reasons.append(行业匹配) else: reasons.append(行业不匹配) employees company.get(employees) if employees and 人 in employees: import re match re.search(r(\d)[-\s]*(\d)?, employees) if match: start int(match.group(1)) if start self.min_employees: score 20 reasons.append(规模达标) if company.get(contact_email): score 20 reasons.append(有公开邮箱) if company.get(summary): score 10 reasons.append(有业务描述) return {**company, score: score, reasons: reasons}这个评分器非常简单实际项目中可以加入更多信号比如“是否正在招聘销售岗位”“是否使用了竞品关键词”等。评分的意义不在于追求绝对精确而是让团队能优先处理高价值线索。4.4 主流程与数据存储新建storage/db.py实现简单的 JSON 存储# storage/db.py import json from pathlib import Path def load_existing(path: str) - list[dict]: p Path(path) if not p.exists(): return [] with open(p, r, encodingutf-8) as f: return json.load(f) def save_leads(path: str, leads: list[dict]): # 按公司名去重 unique {} for lead in leads: name lead.get(company_name) if name and name not in unique: unique[name] lead with open(path, w, encodingutf-8) as f: json.dump(list(unique.values()), f, ensure_asciiFalse, indent2)再写主程序main.py# main.py from agents.sourcing import SourcingAgent from agents.extractor import ExtractorAgent from agents.scorer import LeadScorer from storage.db import load_existing, save_leads # 配置区实际项目可以改成读取 yaml 或环境变量 SEARCH_URL https://www.bing.com/search?q{keyword}B2B软件 LLM_BASE_URL http://localhost:11434/v1 # Ollama 默认地址 LLM_API_KEY ollama LLM_MODEL qwen2.5:7b # 定义目标客户画像 INDUSTRIES [erp, crm, saas, 软件] def main(): sourcing SourcingAgent(SEARCH_URL) extractor ExtractorAgent(LLM_BASE_URL, LLM_API_KEY, LLM_MODEL) scorer LeadScorer(include_industriesINDUSTRIES) keywords [制造企业 CRM, 电商 ERP, 零售 SaaS] leads load_existing(data/leads.json) for kw in keywords: print(f[*] 搜索关键词: {kw}) candidates sourcing.find_candidates(kw, limit3) for url in candidates: print(f - 抓取: {url}) text sourcing.fetch_content(url) if len(text) 50: continue info extractor.extract_company_info(text) if not info: continue lead scorer.score(info) lead[source_url] url lead[keyword] kw leads.append(lead) print(f 收录: {lead.get(company_name)} 评分: {lead[score]}) # 保存结果 save_leads(data/leads.json, leads) print(f[*] 完成共 {len(leads)} 条线索) if __name__ __main__: main()4.5 运行与预期输出启动前先确保本地 LLM 服务已经运行。以 Ollama 为例ollama serve ollama pull qwen2.5:7b然后运行python main.py正常情况下终端会打印每个关键词的搜索和抓取过程。最终在data/leads.json中会看到类似这样的记录[ { company_name: 示例软件有限公司, industry: 企业管理软件, employees: 50-150人, sell_to: 制造企业, contact_email: contactexample.com, summary: 提供面向制造企业的 CRM 和 ERP 解决方案, score: 80, reasons: [行业匹配, 规模达标, 有公开邮箱, 有业务描述], source_url: https://www.example.com, keyword: 制造企业 CRM } ]这个示例虽然简单但已经具备了一个 B2B 潜客代理的最小闭环搜索、抓取、抽取、评分、存储。把这个流程接入 CRM 推送或邮件群发就基本构成了一套可用的系统。5. 常见问题与排查思路5.1 LLM 返回的不是合法 JSON问题现象常见原因解决思路json.loads 报错模型输出包含说明文字或 Markdown用json包裹解析兜底字段缺失prompt 约束不够严格使用 JSON Schema 或 Function Calling抽取结果不稳定模型版本或温度设置问题temperature 设为 0并多次采样取多数建议在开发阶段把所有 LLM 响应都记录到日志里方便回溯。生产环境可以加入重试机制失败后降低输入长度再试一次。5.2 搜索结果页抓取不到外链搜索引擎结果页通常结构会变也不建议高频率抓取。更稳妥的方案是使用官方搜索 API如 Bing Web Search API。自托管 SearXNG通过 JSON 格式返回结果。将常用行业关键词整理成“目标公司名单 官网 URL”跳过搜索环节。5.3 官网正文提取为空可能原因页面是纯 JavaScript 渲染trafilatura无法直接获取。网站有反爬验证需要额外处理 Cookie 或浏览器环境。页面正文太短被误判为无内容。解决思路对关键页面改用 Playwright 渲染后再次提取对低价值页面直接跳过。5.4 重复线索太多判断重复不能只看公司名因为同一家公司可能出现在多个关键词结果中。建议增加域名去重逻辑from urllib.parse import urlparse def domain_of(url): return urlparse(url).netloc.replace(www., )存储时以domain作为唯一键比公司名更可靠。5.5 运行速度太慢如果线索量很大串行请求会非常慢。可以引入协程或线程池来并发抓取但要注意控制并发数避免对目标网站造成压力也避免 IP 被限制。合理范围一般是 5 到 10 个并发。6. 工程化与合规最佳实践6.1 遵守网站访问规则抓取目标网站前建议做三件事查看robots.txt确认哪些路径禁止抓取。设置合理的请求间隔默认建议 3 秒以上。只抓取与销售线索直接相关的公开信息不碰需要登录或授权的页面。如果你的业务涉及大量数据获取建议联系数据源方获取授权或者直接采购第三方商业数据服务。6.2 数据最小化与隐私保护B2B 潜客数据虽然大多是企业公开信息但联系人邮箱、个人姓名等字段依然涉及隐私合规问题。最佳实践是只保留与业务目的直接相关的字段。为数据设置保留期限定期清理无效线索。涉及中国大陆个人信息保护法和海外的 GDPR需要咨询法务意见。不要购买或整合来源不明的数据。6.3 引入人工审核节点AI 代理筛选出的线索应该经过人工确认后再进入销售流程。实践中可以在系统中加入“状态”字段{ status: pending_review # 可选值: pending_review / qualified / rejected / contacted }让销售团队只处理qualified状态的线索能有效避免错杀和误判。6.4 日志与可观测性AI 代理涉及多个外部依赖建议至少记录以下日志搜索关键词和返回结果数量。每个候选页面的抓取耗时和状态。LLM 请求的 token 用量和耗时。评分依据和最终得分。推送 CRM 的成功与失败原因。这样即使某个环节出错也能快速定位。6.5 定期更新线索池B2B 数据时效性强半年前有效的邮箱可能现在已经失效。建议按业务节奏安排定期扫描例如每周增量更新一次每月全量校验一次。通过 MX 记录批量检查邮箱域名是否仍然有效是一种成本很低的健康度校验方式。7. 总结与下一步学习方向开源 AI 代理找 B2B 潜客本质上是把“信息搜集—理解—筛选—执行”这个销售流程自动化。相比传统的爬虫加规则匹配它最大的改进在于用 LLM 处理非结构化文本让系统能理解网页内容中的业务信号而不是只靠关键词硬匹配。本文提供的示例虽然简化但覆盖了整个核心链路搜索线索、抓取网页、LLM 抽取、规则评分、去重存储。在此基础上你可以继续扩展的方向包括接入更多线索源例如招聘公告、融资新闻、开源社区动态。将结果推送至 CRM 系统比如通过 Webhook 或标准 API 对接。增加联系人发现模块从公司域名反查企业邮箱规则。使用本地开源模型替代云端模型降低隐私风险。引入消息队列让抓取、抽取、评分解耦支持更大规模的数据处理。如果你也在做类似的自动化获客工具建议从一个细分行业切入先把 100 条线索的完整流程跑通再逐步扩大数据源。项目的核心难点其实不在于 AI 模型本身而在于数据质量、流程稳定性和合规边界。这也是这类开源项目真正值得长期关注的原因。