猎聘招聘助手 V1
目标
这个 skill 只做两类服务,分开理解、分开执行:
- liepin-screening — 读取推荐页候选人、对照画像筛选、逐人触达打招呼
- liepin-progress — 查看已沟通候选人的回复状态、索要简历
如果用户没有明确指定,默认先进入 liepin-screening。
前置条件(阻断式)
在执行任何猎聘操作之前,必须满足:
- 安装并配置 xbrowser skill(猎聘页面必须通过 xbrowser 控制 Chrome)
- 用户在 Chrome/Chromium 中已登录猎聘招聘者页面
lpt.liepin.com - Chrome 必须以 CDP 调试模式运行(xbrowser 会自动处理此配置)
- 确认用户已提供岗位画像或 JD 要求
如果这些条件未满足,禁止继续。
浏览器规则(硬约束)
xbrowser 独占
猎聘页面的所有操作必须通过 xbrowser(xb.cjs CLI),禁止使用其他浏览器工具。
xb.cjs 路径:~/Library/Application Support/QClaw/openclaw/config/skills/xbrowser/scripts/xb.cjs
命令速查
xb run --browser chrome open <url> # 打开页面
xb run --browser chrome get url # 获取当前URL
xb run --browser chrome wait <ms> # 等待
xb run --browser chrome wait --load networkidle # 等待网络空闲
xb run --browser chrome eval "<js>" # 执行JS表达式
xb run --browser chrome screenshot # 截图
xb run --browser chrome tab # 查看标签页
已知 xbrowser 限制
eval在同一页面上下文中复用变量作用域,每次调用必须使用唯一变量名(如_mdlg、_btns等),避免Identifier has already been declared错误click @ref命令可能不触发完整事件链dialog dismiss不适用于 Ant Design Modal(非原生浏览器 dialog)- ⚠️ xbrowser 存在 tab 漂移 bug(操作过程中自动切到其他 tab),复杂操作建议降级为 Python CDP 直连
猎聘平台特征
页面结构
- 招聘者端:
lpt.liepin.com/recommend(人才推荐页) - 左侧岗位 tab 列表,点击 tab 后 AJAX 刷新候选人列表
- 候选人卡片包含:活跃状态、姓名、年龄、经验年限、学历、期望城市/薪资/岗位、行业、公司、职位、技能关键词
- 每张卡片有「立即沟通」按钮(Ant Design 组件)
- 排序方式:推荐 / 最新(radio)
触达通道
猎聘招聘者端触达通道有两个按钮:
| 按钮 | 通道 | 是否消耗超级聊聊权益 | 默认话术 | 适用场景 | |------|------|----------------------|----------|----------| | 「立即沟通」 | 打招呼(免费) | ❌ 不消耗 | "你好,看了你的简历,方便聊聊吗" | 默认使用(不消耗权益+反爬虫检测更宽松) | | 「超级聊聊」 | 付费打招呼 | ✅ 消耗 | 弹窗模板(可改) | 自定义话术/重要候选人 |
DOM 关键类名
- 立即沟通按钮:
button.ant-lpt-btn.ant-lpt-btn-primary - 弹窗:
.ant-modal(Ant Design Modal) - 弹窗关闭按钮:
.antlpticon-close - 推荐页卡片容器:
.newResumeItem--ppozw或.nest-resume-personal - 搜索页卡片容器:
.nest-resume-personal
候选人列表读取 recipe
推荐页列表提取
xb run --browser chrome eval '(function(){
const btns = Array.from(document.querySelectorAll("button"))
.filter(b=>b.textContent.trim()==="立即沟通");
const results = [];
btns.forEach((b,i) => {
let el = b.parentElement;
for(let d=0; d<7; d++){
if(!el) break;
const t = el.textContent.replace(/\s+/g," ").trim();
if(t.length > 30 && t.length < 500){
results.push(i+": "+t.substring(0,130));
break;
}
el = el.parentElement;
}
});
return results.join("\n---\n");
})()'
搜索页列表提取
# 打开搜索页
xb run --browser chrome open https://lpt.liepin.com/search
# 等待加载
xb run --browser chrome wait 2000
# 提取候选人(搜索页卡片容器结构与推荐页相同)
xb run --browser chrome eval '(function(){
const btns = Array.from(document.querySelectorAll("button"))
.filter(b=>b.textContent.trim()==="立即沟通");
const results = [];
btns.forEach((b,i) => {
let el = b.parentElement;
for(let d=0; d<7; d++){
if(!el) break;
const t = el.textContent.replace(/\s+/g," ").trim();
if(t.length > 30 && t.length < 500){
results.push(i+": "+t.substring(0,130));
break;
}
el = el.parentElement;
}
});
return results.join("\n---\n");
})()'
触达 recipe
推荐页触达
❌ 绝对禁止:
- 用固定索引(如
btns[3])跨轮定位候选人按钮 - 先批量收集索引再回头逐一点击
原因: 每触达一人,列表可能重排,索引会漂移。
✅ 正确方式:
使用候选人唯一特征(姓名 + 公司名)匹配按钮。每次触达都重新走"获取列表 → 特征匹配 → 点击"流程:
xb run --browser chrome eval '(function(){
const btns = Array.from(document.querySelectorAll("button"))
.filter(b=>b.textContent.trim()==="立即沟通");
for(let b of btns){
let el = b.parentElement;
for(let d=0; d<7; d++){
if(!el) break;
const t = el.textContent;
if(t.includes("候选人姓名") && t.includes("公司名")){
b.click();
return "clicked";
}
el = el.parentElement;
}
}
return "not found";
})()'
触达一人后必须:
wait 2500等待弹窗出现- 关闭弹窗(见弹窗关闭 recipe)
wait 1500等待列表更新- 重新获取候选人列表(索引已变化)
- 再定位下一个目标
搜索页触达(多一步职位选择)
搜索页「立即沟通」点击后会弹出「请选择开聊职位」对话框,必须完成职位选择才能发送。
# Step 1: 点击 立即沟通
xb run --browser chrome eval '(function(){
const btns = Array.from(document.querySelectorAll("button"))
.filter(b=>b.textContent.trim()==="立即沟通");
// 找到目标候选人(姓名+公司唯一匹配)
for(let b of btns){
let el = b.parentElement;
for(let d=0; d<7; d++){
if(!el) break;
const t = el.textContent;
if(t.includes("候选人姓名") && t.includes("公司名")){
b.click();
return "step1-clicked";
}
el = el.parentElement;
}
}
return "not found";
})()'
xb run --browser chrome wait 1500
# Step 2: 在弹窗中选择目标职位(匹配职位名+薪资范围)
xb run --browser chrome eval '(function(){
const lis = document.querySelectorAll("li");
for(let i=0;i<lis.length;i++){
const t = lis[i].textContent;
// 匹配职位名和薪资(例如"销售经理25-35k")
if(t.indexOf("销售经理")>=0 && t.indexOf("25-35k")>=0){
lis[i].click();
return "step2-selected";
}
}
return "position-not-found";
})()'
xb run --browser chrome wait 500
# Step 3: 点确认
xb run --browser chrome eval '(function(){
const btns = document.querySelectorAll("button");
for(let i=0;i<btns.length;i++){
if(btns[i].textContent.trim()==="确认"){
btns[i].click();
return "step3-confirmed";
}
}
return "confirm-not-found";
})()'
⚠️ 搜索页致命错误: 关闭弹窗而不点确认 = 取消发送,触达失败。
弹窗关闭 recipe
推荐页「立即沟通」无弹窗,直接关闭(若有)。超级聊聊弹窗关闭:
xb run --browser chrome eval '(function(){
const closeIcon = document.querySelector(".antlpticon-close");
if(closeIcon){ closeIcon.click(); return "closed"; }
return "no close";
})()'
备用方案(文本匹配):
xb run --browser chrome eval '(function(){
const btns = document.querySelectorAll("button");
for(let b of btns){
if(b.textContent.includes("关闭")){ b.click(); return "closed-btn"; }
}
return "no close found";
})()'
推荐页 vs 搜索页
| 场景 | 推荐页 | 搜索页 | |------|--------|--------| | 需要大批量快速筛选 | ✅ 候选池更大(40+17+岗位) | ⚠️ 每轮仅20人,不可翻页 | | 需要精确关键词匹配 | ❌ AI驱动,不可控 | ✅ 关键词精确控制 | | 需要精确岗位筛选 | ✅ 左侧tab切换 | ❌ 关键词包含 | | 触达操作复杂度 | ✅ 一键发送 | ⚠️ 需三步(点击→选职位→确认) |
推荐策略: 推荐页为主(候选池大) + 搜索页为辅(精准关键词补充)
搜索页扩池方法
换关键词多轮搜索,每次返回不同候选池:
"深圳 能源 销售" → "广州 新能源 销售总监" → "电力 大客户销售" → ...
⚠️ 每轮硬性上限20人,不可翻页。大量换词搜索可覆盖更多候选人。
画像匹配基础原则
1. 硬性条件(学历/经验年限/行业/Base地)必须全部满足 → 才进入画像打分
2. 满足全部必须项 → 直接触达,不设人数上限
3. 画像打分 ≥60-70% → 触达
4. 禁止机械标签匹配:看到"软件销售"等关键词不能直接放行,必须结合岗位行业语境
触达规则
- 触达阈值:满足画像 ≥60-70% 或满足全部必须项 → 直接触达
- 不设人数上限:满足条件的全部触达
- 默认使用「立即沟通」打招呼(不消耗权益 + 反爬虫宽松)
- 一人一事务:触达一人 → wait 30s+ → 触达下一个
- 如果连续 2 人触达失败:检查是否触发风控,暂停并汇报
- 紧急停手情形:批量 5 次「超级聊聊」全部失败 → 暂停使用付费通道
进度汇报格式
每次完成一轮筛选触达后,汇报:
- 本轮获取候选人总数
- 符合画像的候选人列表(按匹配度排序)
- 已触达候选人及匹配度
- 本轮耗时与触达成功率
- 是否建议翻页/换排序/换岗位继续
常见问题与排错
| 问题 | 原因 | 解决 |
|------|------|------|
| wait --load networkidle 超时 | 页面持续轮询 | 改用 wait 2000 固定等待 |
| Identifier X has already been declared | eval 作用域变量冲突 | 使用唯一前缀变量名如 _mdlg, _btns2 |
| click @ref 不触发弹窗 | xbrowser click 不走完整事件链 | 改用 eval + element.click() |
| 卡在 closest("div") 取不到文本 | DOM 层级不符合预期 | 用 parentElement 循环遍历 5-7 层 |
| 触达后候选人还在列表 | 弹窗未正确关闭 | 截图确认页面状态 |
| 列表完全刷新 | 页面自动重载 | 正常行为,重新获取 |
| 搜索页关弹窗后无变化 | 关弹窗=取消发送,触达失败 | 必须点确认才生效 |
任务结束后的 Chrome 清理(强制规则)
每次猎聘任务执行结束后,必须执行以下流程:
- 主动询问用户:任务完成后,必须向用户发起询问——"猎聘任务已结束,是否强制关闭 Chrome 浏览器?"
- 获得明确答复:
- 用户回答"是" / "关" / "关闭" / "可以" / "行" 等肯定答复 → 立即执行
xb stop chrome --force - 用户回答"否" / "不关" / "等一下" / "先不管" 等否定答复 → 不关闭,告知用户"Chrome 保持运行,记得任务结束后手动关闭"
- 用户回答"是" / "关" / "关闭" / "可以" / "行" 等肯定答复 → 立即执行
- 不得跳过:不得在未询问用户的情况下自行关闭或自行保持 Chrome 运行
微信扫一扫