基于OpenClaw框架的智能求职助手:自动化信息采集与AI匹配实战
1. 项目概述:一个帮你“躺平”找工作的智能助手
最近在折腾一个挺有意思的自动化项目,叫 OpenClaw Job Hunter。简单来说,它就是一个基于 OpenClaw 智能体框架的“求职机器人”。作为一个在技术圈摸爬滚打多年的老鸟,我深知找工作的过程有多繁琐:每天要像上班打卡一样,去刷 BOSS 直聘、看牛客网、翻小红书和公众号的内推帖,还得手动记录和筛选,费时费力。这个项目的核心思路,就是把这套重复劳动完全自动化——让它每天定时去各大平台帮你“巡逻”,找到新发布的、匹配你需求的岗位,然后经过 AI 智能打分,把结果直接推送到你的飞书多维表格里,你只需要打开手机看看推送结果就行。
这个 Skill 的设计初衷,就是解放求职者的时间,把精力聚焦在准备面试和提升技能上,而不是浪费在信息搜集上。它特别适合正在积极寻找机会的技术从业者,尤其是程序员、产品经理、运营等岗位,当然,它的框架是通用的,只要你稍作调整,也能用于其他领域的求职。项目内置的渠道目前主要针对国内求职市场,但整个 Skill 的结构设计得非常灵活,你可以很方便地添加领英、Indeed 或者其他地区的招聘网站。
2. 核心设计思路与架构拆解
2.1 为什么选择 OpenClaw 框架?
在开始动手之前,我评估过几种方案,比如自己写爬虫脚本配合定时任务,或者用一些 RPA 工具。最终选择 OpenClaw,主要是看中了它的“智能体”特性。OpenClaw 不是一个简单的爬虫库,而是一个能理解任务、调用工具、做决策的框架。对于求职信息采集这种场景,不同网站的反爬策略、页面结构天差地别,一个固定的爬虫脚本很容易挂掉。
OpenClaw 允许我定义一套“策略”:针对 BOSS 直聘这种反爬严格的,就用web_search工具通过搜索引擎间接获取信息;对于小红书、公众号这种需要处理 JavaScript 动态内容的,就启用browser工具进行真实的浏览器模拟。这种根据目标“智能”选择最佳工具的能力,是传统脚本难以实现的,也让整个系统的健壮性和适应性大大提升。
2.2 三层去重机制的设计考量
信息过载和重复是自动化采集的大敌。如果同一个岗位今天从 BOSS 直聘抓到,明天从小红书又抓到一次,会严重干扰判断。这个项目设计了一套三层递进式的去重机制,确保推送给你的都是“新”且“准”的信息。
- 本地 SQLite 缓存去重:这是第一道防线。每次爬取到的职位 URL 都会存入一个本地的 SQLite 数据库 (
crawl_cache.db)。下次运行时,会先查询缓存,如果 URL 已存在且未过期(例如7天内),则直接跳过。这能避免短时间内对同一链接的重复抓取,极大节省资源和时间。 - 飞书历史记录去重:这是第二道防线,也是业务逻辑上去重的关键。本地缓存可能会被清空,或者你换了台机器运行。因此,在准备向飞书表格写入一条新记录前,程序会先去查询表格中是否已经存在“公司名+职位名”相同的记录。这一步防止了因缓存失效导致的重复推送。
- AI 语义匹配去重:这是最智能的一层。有些岗位,不同渠道的描述可能略有差异,但本质是同一个职位。单纯依靠 URL 或关键词匹配可能会漏掉。这里会调用 OpenClaw 的 LLM 能力,将新抓取的职位描述与飞书表格中已有的记录进行语义相似度比对。如果 AI 判断为高度重复,即使前两层没拦住,这一层也会将其过滤掉。这样确保了信息流的纯净。
2.3 多渠道策略与工具选型
渠道策略表是这个项目的核心配置之一,它直接决定了信息获取的广度和质量。我的设计原则是:为每个渠道选择最稳定、最不容易被屏蔽的采集方式。
- BOSS 直聘 (web_search):这是反爬虫的重灾区,直接请求其页面几乎立刻会被封。因此,策略是放弃直接抓取,转而使用
web_search工具(背后是 Brave Search API)去搜索“公司名 + 招聘”这样的关键词,从搜索引擎的结果摘要中提取信息。虽然信息不如官网完整,但能拿到公司、职位、地点等核心信息,且极其稳定。 - 小红书/微信公众号 (browser):这两个平台的内容严重依赖 JavaScript 渲染,且公众号文章需要通过搜狗微信搜索。使用
browser工具启动一个无头浏览器,可以完美模拟真人操作,登录、滚动、点击翻页都不在话下,能获取到最完整的内容。 - 技术社区 (browser):牛客、力扣、V2EX、掘金等社区,虽然反爬不严,但页面结构复杂,且常有登录态要求。统一使用
browser工具处理,代码逻辑一致,维护起来更方便。通过 CSS 选择器精准定位帖子标题、链接和发布时间即可。 - 自由搜索 (web_search + web_fetch):这是一个补充渠道。用于发现那些不在预设渠道列表里的机会,比如某个公司的官方招聘页、某个技术博客发布的内推信息。先通过
web_search找到相关链接,再用web_fetch去抓取页面内容进行分析。
注意:
web_fetch工具在 Clash TUN 模式下可能会遇到问题,因为该模式会使用198.18.0.0/15这类 RFC 2544 保留地址进行 Fake IP 映射,而web_fetch默认出于安全考虑会拦截对这类内网地址的请求。需要在 OpenClaw 配置中显式允许,配置方法在后续章节会详细说明。
3. 环境准备与详细配置指南
3.1 OpenClaw 基础环境搭建
首先,你需要一个可运行的 OpenClaw 环境。建议参考其官方文档进行安装,这里我强调几个关键点。
- 安装与初始化:通常使用 pip 安装后,需要通过
openclaw gateway命令启动网关服务。首次运行会引导你进行初步配置,包括选择大模型(如 OpenAI GPT-4, Claude 3,或本地部署的模型)和设置 API Key。确保你的网络环境能稳定访问你所选模型的接口。 - 启用必要的工具:在 OpenClaw 的配置文件 (
~/.openclaw/openclaw.json) 中,你必须确保以下工具被启用:{ "tools": { "browser": { "enabled": true // 用于抓取动态网页 }, "web": { "search": { "enabled": true // 用于网页搜索 }, "fetch": { "enabled": true // 用于抓取静态网页 } } } } - 配置 Brave Search API:
web_search工具依赖 Brave Search。你需要去 Brave Search 官网 申请一个免费的 API Key,然后在配置文件中指定:{ "tools": { "web": { "search": { "apiKey": "YOUR_BRAVE_SEARCH_API_KEY" } } } }
3.2 飞书机器人创建与表格配置
飞书多维表格是本项目的数据终点,配置稍显繁琐但一劳永逸。
- 创建多维表格:在飞书桌面端或网页端,新建一个多维表格。我建议的列包括:
职位名称、公司名称、工作地点、薪资范围、职位来源、原始链接、匹配度分数、抓取时间、备注。你可以根据自己需求增减。 - 获取表格 ID:打开你创建好的表格,浏览器地址栏的 URL 中,
base/后面那一长串字符串就是TABLE_ID。例如:https://example.feishu.cn/base/Tblxxxxxxxxxxxxxxx?table=xxxxxxxxx。 - 创建自定义机器人:
- 进入飞书开放平台,创建企业自建应用。
- 在应用的功能权限中,为机器人添加“获取访问凭证”和“读写多维表格”的权限。
- 发布应用版本,并等待审核通过(通常很快)。
- 在开放平台后台,进入你的应用,在“凭证与基础信息”页面,可以拿到
App ID和App Secret。这两个信息等同于项目 README 里提到的APP_TOKEN,需要妥善保管。
- 获取表格的读写权限:仅仅有机器人权限还不够,必须将机器人添加为这个多维表格的协作者。在表格页面点击分享按钮,在“添加协作者”中搜索你刚刚创建的机器人名称,并赋予其“可编辑”权限。
3.3 Job Hunter Skill 的部署与个性化
接下来是部署本项目代码并进行个性化配置。
- 克隆与放置:
# 我推荐使用自定义目录,方便管理 git clone https://github.com/boat2moon/openclaw-job-hunter.git ~/my-openclaw-skills/job-hunter - 修改 OpenClaw 配置以加载自定义技能目录:编辑
~/.openclaw/openclaw.json,添加extraDirs路径。{ "skills": { "load": { "extraDirs": ["/Users/yourname/my-openclaw-skills"] // 注意填写你的绝对路径 } } } - 配置求职偏好 (
references/job-profile.md):这是 AI 为你筛选和打分的关键依据。务必认真填写。## 求职偏好 * **目标城市**:北京、上海、杭州、远程 * **期望薪资**:月薪 30k - 50k,或年薪 50w+ * **公司类型**:互联网大厂(字节、腾讯、阿里等)、有潜力的 B 轮后初创公司、外企 * **职位方向**:后端开发、技术专家、架构师 * **技术栈偏好**:Go/Python, Kubernetes, 微服务, 云计算 * **排除关键词**:外包、销售、保险、单休、大小周 - 配置简历信息 (
references/resume.md):AI 会将职位要求与你的简历进行匹配打分。你可以直接粘贴简历文本,或者更推荐的做法是,将你的在线简历(如看准网、LinkedIn 公开页)URL 放在这里。## 我的简历 https://www.zhipin.com/resume/xxxxxxx // 在线简历链接,信息更全面 - 配置飞书信息 (
SKILL.md):打开项目根目录下的SKILL.md文件,找到类似YOUR_APP_TOKEN和YOUR_TABLE_ID的占位符,替换为你上一步获取的真实信息。// 在 SKILL.md 中找到配置部分 "feishu_app_token": "你的 App ID | 你的 App Secret", "feishu_table_id": "你的多维表格 Table ID",
实操心得:在配置
job-profile.md时,尽量具体。“互联网公司”就不如“字节、腾讯、阿里”明确。“高薪资”也不如“月薪30k以上”明确。越具体,AI 的匹配和过滤就越精准,能帮你节省大量浏览无关信息的时间。
4. 核心工作流程与代码逻辑剖析
4.1 主流程解析:从触发到推送
整个 Skill 的执行流程被定义在SKILL.md的steps部分,这是一个清晰的、可解释的工作流。
- 触发与初始化:当你通过 OpenClaw 网关发送“帮我找一下最新的招聘岗位”或使用
/job-hunter命令时,Skill 被激活。它首先会加载job-profile.md和resume.md中的配置,作为本次任务的上下文。 - 多渠道并行采集:这是最耗时的环节。Skill 会根据预设的策略表,为每个渠道创建一个子任务。例如,
browser工具会打开一个无头 Chrome 实例,模拟访问小红书,滚动页面,解析出帖子列表;而web_search则会并发地向 Brave Search 发送多个查询请求。这里 OpenClaw 框架的优势体现出来了:这些工具调用是异步并发的,大大缩短了总采集时间。 - 数据清洗与标准化:从不同渠道抓取到的原始数据是五花八门的 HTML 片段或 JSON 片段。这一步会使用一系列预定义的解析规则(正则表达式、CSS 选择器、JSON Path)从中提取出结构化的字段:职位名、公司名、地点、薪资、链接、发布日期等。并统一格式,例如将薪资“20-40K”统一转换为数字范围
[20000, 40000],方便后续比较。 - 三层去重过滤:对上一步得到的结构化数据列表,依次应用之前提到的三层去重。首先用
cache_manager.py脚本查询本地 SQLite 缓存,然后调用飞书 API 查询历史记录,最后对剩余的“疑似新岗位”调用 LLM 进行语义去重。通过这三关的岗位,才会进入下一环节。 - AI 匹配与打分:这是核心的智能环节。对于每一个候选岗位,OpenClaw 会构造一个 Prompt,将岗位描述(JD)和你的简历(或简历链接)一起提交给 LLM,要求其从“技术栈匹配度”、“经验要求匹配度”、“公司文化匹配度”、“薪资竞争力”等多个维度进行打分(例如百分制),并给出简短的匹配理由。这个分数是后续排序和决策的关键。
- 飞书表格写入:将最终筛选出的岗位信息,连同 AI 匹配分数和理由,按照飞书多维表格的 API 格式要求,批量写入到指定的表格中。写入时会包含抓取时间戳和来源渠道。
- 缓存更新与总结:将本次成功写入的岗位 URL 更新到本地 SQLite 缓存中,标记抓取时间。最后,Skill 会向用户返回一个总结,例如“今日共扫描8个渠道,发现新岗位15个,经去重和匹配后,向您的飞书表格推送了5个高匹配度岗位”。
4.2 缓存管理器 (cache_manager.py) 详解
这个脚本虽小,但至关重要,它负责管理本地的 URL 去重缓存。
# cache_manager.py 核心逻辑示意 import sqlite3 from datetime import datetime, timedelta class CrawlCacheManager: def __init__(self, db_path='data/crawl_cache.db'): self.conn = sqlite3.connect(db_path) self._create_table() def _create_table(self): # 创建简单的 url -> last_crawl_time 映射表 cursor = self.conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS crawl_cache ( url TEXT PRIMARY KEY, last_crawl_time TIMESTAMP ) ''') self.conn.commit() def is_url_crawled_recently(self, url, expiry_days=7): """检查URL是否在近期(如7天内)已被抓取过""" cursor = self.conn.cursor() cursor.execute( "SELECT last_crawl_time FROM crawl_cache WHERE url = ?", (url,) ) row = cursor.fetchone() if row: last_time = datetime.fromisoformat(row[0]) if datetime.now() - last_time < timedelta(days=expiry_days): return True # 近期已抓,跳过 return False # 需要抓取 def update_cache(self, url): """将URL的抓取时间更新为当前时间""" cursor = self.conn.cursor() now_iso = datetime.now().isoformat() cursor.execute( "INSERT OR REPLACE INTO crawl_cache (url, last_crawl_time) VALUES (?, ?)", (url, now_iso) ) self.conn.commit()它的工作模式是“先查后更新”。在抓取前查询,避免重复劳动;在成功处理(并计划推送)后更新,记录本次抓取。expiry_days参数(默认7天)很关键,它意味着一个岗位信息在本地缓存里只保留一周的“新鲜度”,超过一周后,即使 URL 在缓存中,也会被重新抓取,以防岗位信息(如薪资、要求)已更新。
4.3 AI 匹配打分的 Prompt 工程
如何让 LLM 给出客观、有用的匹配分数?这依赖于精心设计的 Prompt。在SKILL.md中,你会看到一个专门用于匹配打分的步骤。
你是一个专业的招聘顾问。请对比以下【职位描述】和【候选人简历】,从以下几个维度进行匹配度分析,并给出一个0-100的综合匹配分数。 维度包括: 1. 技术栈匹配度(主要编程语言、框架、工具是否吻合) 2. 经验与资历匹配度(要求的年限、项目经验是否匹配) 3. 职责范围匹配度(工作内容是否与候选人过往经历相关) 4. 软技能与文化匹配度(沟通、团队协作等要求是否匹配候选人特质) 5. 薪资与职级匹配度(根据简历推断的当前职级与薪资,与该岗位的竞争力) 【职位描述】 {job_description} 【候选人简历】 {resume_content} 请按以下格式输出: 综合匹配分数:[0-100的整数] 匹配理由:[针对上述维度,用分点简述理由,每点不超过一句话]这个 Prompt 明确了角色、任务、评价维度和输出格式。将开放性的问题结构化,能极大提高 LLM 回复的稳定性和可比性。不同的岗位,即使来自不同渠道,其匹配分数也是基于同一套标准产生的,这使得排序和筛选变得有意义。
5. 高级配置与调优技巧
5.1 应对 Clash TUN 模式的网络问题
如果你使用的是 Clash Verge 的 TUN(增强)模式,并开启了 Fake IP 功能,可能会遇到web_fetch工具报错,提示访问被拒绝。这是因为 Fake IP 模式使用了198.18.0.0/15这个 RFC 2544 定义的 Benchmark 测试地址段,而web_fetch默认出于安全考虑(防止 Server-Side Request Forgery 攻击)会阻止对内网 IP 的请求。
解决方法是在 OpenClaw 配置中明确允许这个地址段:
{ "tools": { "web": { "fetch": { "ssrfPolicy": { "allowRfc2544BenchmarkRange": true // 关键配置 } } } } }修改配置后,需要重启 OpenClaw Gateway 服务使其生效。这个配置告诉web_fetch工具:“允许向 198.18.x.x 这样的地址发起请求”,从而解决了在 TUN 模式下的网络连通性问题。
5.2 自定义与扩展采集渠道
项目内置的渠道可能不完全符合你的需求。扩展新的渠道非常简单,本质上就是在SKILL.md的steps部分增加一个新的“子任务”。
假设你想增加“脉脉”作为新的渠道:
- 分析渠道特性:脉脉是一个需要登录的社交招聘平台,页面是动态渲染的。因此,采集方式应选择
browser。 - 定义采集步骤:在 Skill 的
steps列表中,添加一个新的步骤对象。这个步骤需要:name: 一个描述性名称,如crawl_maimai。tool: 指定为browser。input: 编写清晰的指令,告诉浏览器要做什么。例如:“访问脉脉职场版,搜索‘后端开发 北京’相关的动态,滚动加载5页,将包含招聘信息的帖子标题、公司、链接和发布时间提取出来,以 JSON 格式返回。”parse: 指定如何从浏览器工具返回的复杂结果中,解析出我们需要的结构化数据。这可能需要你写一小段 JavaScript 代码,在浏览器上下文中执行,利用 DOM API 来提取信息。
- 集成到主流程:确保这个新步骤被加入到并行采集的阶段中,并且其输出会流入后续的数据清洗、去重和打分流程。
注意事项:添加
browser渠道时,如果目标网站需要登录,你需要在 OpenClaw 的浏览器工具配置中预先设置好 Cookies 或登录态。通常的做法是,先手动用该浏览器工具登录一次网站,其会话状态会被保留下来供后续使用。
5.3 调整匹配算法与推送阈值
默认的 AI 打分是综合多个维度的结果。你可以通过修改 Prompt 来调整打分倾向。例如,如果你当前最看重薪资,可以将 Prompt 中“薪资与职级匹配度”的权重提高,或者要求 LLM 先给出各维度分数,然后你写一个后处理函数进行加权计算。
推送阈值也可以在 Skill 逻辑中设置。例如,你可以在写入飞书表格前加一个判断:只推送综合匹配分数大于 70 分的岗位。这个阈值可以在job-profile.md中作为一个配置项,实现个性化过滤。
# 在 job-profile.md 中增加 推送设置: 最低匹配分数: 70 忽略未标明薪资的岗位: 是 只推送24小时内发布的岗位: 是然后,在SKILL.md的流程中,读取这个配置,并在 AI 打分步骤后,根据这些条件进行过滤。
6. 常见问题排查与实战心得
6.1 问题排查清单
在实际运行中,你可能会遇到以下问题,这里提供排查思路:
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| Skill 执行后,飞书表格无任何新数据 | 1. 飞书配置错误(Token、Table ID) 2. 网络问题导致 API 调用失败 3. 所有渠道均未抓到新数据,或数据全被去重过滤 | 1. 检查SKILL.md中的飞书配置是否正确,特别是 Token 的格式(AppID|AppSecret)。2. 查看 OpenClaw Gateway 的运行日志,是否有明显的 API 错误信息。 3. 临时修改代码或配置,关闭去重逻辑,看是否有数据被推送,以确定是采集问题还是过滤问题。 |
浏览器工具 (browser) 启动失败或超时 | 1. 未安装 Chrome/Chromium 2. 系统内存不足 3. 网络代理导致连接超时 | 1. 确保系统已安装 Chrome/Chromium,并且版本与 OpenClaw 的 puppeteer 兼容。 2. 检查系统资源。可以尝试在 OpenClaw 配置中为 browser工具设置headless: true和更低的超时时间。3. 如果使用代理,确保 OpenClaw 的浏览器配置能正确使用代理。 |
web_search返回结果为空或错误 | 1. Brave Search API Key 无效或过期 2. 搜索关键词过于宽泛或特殊 3. API 调用额度用尽 | 1. 在 Brave Search 官网检查 API Key 状态。 2. 尝试在 Skill 的搜索指令中使用更具体、更常见的关键词组合。 3. 查看 Brave Search API 的用量统计。 |
| AI 匹配分数普遍很低或很不合理 | 1. 简历信息 (resume.md) 过于简略2. Prompt 设计可能不适合你的领域 3. 使用的 LLM 能力不足 | 1. 提供更详细的简历内容,最好是在线简历链接,信息更全面。 2. 根据你的求职领域(如设计、市场)微调打分维度和 Prompt 表述。 3. 考虑在 OpenClaw 配置中切换为更强大的模型,如 GPT-4。 |
| 运行速度非常慢 | 1. 渠道过多,串行执行 2. browser工具每个页面等待时间过长3. 网络延迟高 | 1. 确认 OpenClaw 步骤配置是否为并行执行(通常框架会优化)。 2. 在 browser工具的input中,可以尝试设置更短的超时 (timeout) 和等待选择器出现的时间 (waitForSelector)。3. 对于非关键渠道,可以考虑降低采集频率(如隔天运行)。 |
6.2 实战经验与技巧分享
启动策略:从简到繁:第一次运行时,建议先在
SKILL.md中注释掉大部分渠道,只留一两个(如“自由搜索”)进行测试。确保飞书推送、AI打分整个流程能跑通后,再逐步启用更多渠道。这样可以快速定位问题是出在流程上,还是某个特定渠道上。维护成本:渠道失效是常态:互联网网站的页面结构经常变化。可能上个月还能用的小红书采集规则,这个月就失效了。这是此类自动化项目最大的维护成本。你需要定期(比如每两周)检查一下各渠道的采集效果。一个技巧是,在飞书表格中增加一个“抓取状态”或“原始片段”列,当某个渠道连续多次返回空数据或奇怪数据时,能快速发现。
数据质量优于数量:不要盲目追求抓取的岗位数量。在
job-profile.md中把筛选条件设得严格一些,在 AI 打分环节把推送阈值设得高一些。每天收到 3-5 个高度匹配的岗位推荐,远比收到 50 个杂乱无章的信息要有价值得多。你的时间是有限的,应该用在刀刃上。结合人工复核:这个工具是“助手”,不是“决策者”。AI 打分再高,也可能有误判。建议你每天花 5-10 分钟快速浏览一下推送到飞书表格里的岗位,特别是“匹配理由”部分,看看 AI 的判断是否符合你的直觉。长期下来,你也能反过来优化你的
job-profile.md和简历描述,让人机配合更默契。关于隐私:你的简历和求职偏好是敏感信息。确保
references/目录下的job-profile.md和resume.md文件不被提交到公开的 Git 仓库(项目本身的.gitignore已经排除了references/目录)。如果你使用云服务器运行,也要注意服务器的安全性。
这个 OpenClaw Job Hunter 项目,我把它看作是一个“可编程的求职信息中枢”。它最大的价值不在于替代你找工作,而在于帮你构建一个高效、自动化的信息漏斗,把嘈杂的互联网招聘信息流,过滤成一份为你量身定制的、每日更新的优质机会清单。
