Back to skills
extension
Category: Productivity & OfficeNo API key required

hiring-assistant-LIEPIN

猎聘招聘平台 Skill V1。覆盖 xbrowser 浏览器控制→推荐页/搜索页双模式读取→画像匹配→逐人触达→验证汇报。通用性方法论,不含具体岗位画像。触发词:猎聘、liepin、lpt.liepin.com、猎聘人才推荐、猎聘触达、猎聘筛选、猎聘打招呼。

personAuthor: zhuziyuehubModelScope

猎聘招聘助手 V1

目标

这个 skill 只做两类服务,分开理解、分开执行:

  1. liepin-screening — 读取推荐页候选人、对照画像筛选、逐人触达打招呼
  2. liepin-progress — 查看已沟通候选人的回复状态、索要简历

如果用户没有明确指定,默认先进入 liepin-screening

前置条件(阻断式)

在执行任何猎聘操作之前,必须满足:

  1. 安装并配置 xbrowser skill(猎聘页面必须通过 xbrowser 控制 Chrome)
  2. 用户在 Chrome/Chromium 中已登录猎聘招聘者页面 lpt.liepin.com
  3. Chrome 必须以 CDP 调试模式运行(xbrowser 会自动处理此配置)
  4. 确认用户已提供岗位画像或 JD 要求

如果这些条件未满足,禁止继续。

浏览器规则(硬约束)

xbrowser 独占

猎聘页面的所有操作必须通过 xbrowserxb.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";
})()'

触达一人后必须:

  1. wait 2500 等待弹窗出现
  2. 关闭弹窗(见弹窗关闭 recipe)
  3. wait 1500 等待列表更新
  4. 重新获取候选人列表(索引已变化)
  5. 再定位下一个目标

搜索页触达(多一步职位选择)

搜索页「立即沟通」点击后会弹出「请选择开聊职位」对话框,必须完成职位选择才能发送。

# 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. 禁止机械标签匹配:看到"软件销售"等关键词不能直接放行,必须结合岗位行业语境

触达规则

  1. 触达阈值:满足画像 ≥60-70% 或满足全部必须项 → 直接触达
  2. 不设人数上限:满足条件的全部触达
  3. 默认使用「立即沟通」打招呼(不消耗权益 + 反爬虫宽松)
  4. 一人一事务:触达一人 → wait 30s+ → 触达下一个
  5. 如果连续 2 人触达失败:检查是否触发风控,暂停并汇报
  6. 紧急停手情形:批量 5 次「超级聊聊」全部失败 → 暂停使用付费通道

进度汇报格式

每次完成一轮筛选触达后,汇报:

  1. 本轮获取候选人总数
  2. 符合画像的候选人列表(按匹配度排序)
  3. 已触达候选人及匹配度
  4. 本轮耗时与触达成功率
  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 清理(强制规则)

每次猎聘任务执行结束后,必须执行以下流程:

  1. 主动询问用户:任务完成后,必须向用户发起询问——"猎聘任务已结束,是否强制关闭 Chrome 浏览器?"
  2. 获得明确答复
    • 用户回答"是" / "关" / "关闭" / "可以" / "行" 等肯定答复 → 立即执行 xb stop chrome --force
    • 用户回答"否" / "不关" / "等一下" / "先不管" 等否定答复 → 不关闭,告知用户"Chrome 保持运行,记得任务结束后手动关闭"
  3. 不得跳过:不得在未询问用户的情况下自行关闭或自行保持 Chrome 运行