工作捕手(job-offer-radar)· 自动追踪岗位清单
帮正在找工作、求职、失业、转岗的人自动筛选全网招聘岗位,生成一份专属的 HTML 岗位追踪清单,让求职者一眼看清「哪些岗位值得投」。像棒球场的捕手一样,把散落在各平台的合适岗位一张张接住、摆到你面前。
这个技能能帮你做什么(使用者必读)
- 全网搜岗,只给真实岗位:自动扫猎聘/智联/BOSS直聘/前程无忧51job/筑招网等平台,每个岗位都打开详情页核实「还在招」,链接全部是详情页直达(拒绝列表页假链接),杜绝「投了才发现岗位早没了」
- 按你的条件硬过滤:城市区域、薪资门槛、学历要求(含统招/非统招机筛风险识别)、技术栈黑名单、行业方向——不符合的直接剔除并显式告诉你为什么被剔
- 岗位追踪页:可交互 HTML 清单,可搜索、可标记「已投递/面试中/已拿offer」,历史投递状态跨版本保留
- 匹配度分析 + 打招呼用语:每个岗位给出命中项/能力缺口/硬伤提醒,并生成可直接使用的分段落打招呼语
- 长期陪伴式更新:说一句「更新岗位清单」就增量补新岗、清失效岗,投递状态不丢;token 消耗随变化量而非清单大小增长
- 目标企业拓企:不止搜岗位,还能按「杰出雇主榜单 / 专精特新名单 / 细分行业龙头」三类名单帮你挖出目标企业,再反查这些企业在招的岗位
核心价值
- 求职者不用每天刷十几个招聘平台,你帮他自动扫一遍
- 严格按他的条件过滤,只留符合要求的岗位,标注重点企业和匹配度
- 输出可交互的 HTML:可搜索、可标记投递状态、可直达详情页
- 后续可反复更新:把新岗位追加进同一份 HTML(保留历史岗位和投递状态)
工作流程(严格按顺序执行)
第 1 步:收集用户画像(必须,不可跳过)
先收集画像再搜索。 画像不全会导致筛选失准,这是本技能最重要的步骤,缺失关键信息会浪费一次完整搜索。
用自然对话引导用户提供以下信息(缺哪项问哪项,不要一次性丢一堆问题):
1. 姓名/称呼:用于页面头部展示
2. 求职目标:目标城市 + 可接受的具体区域(如「杭州西湖区/滨江区」——以用户实际目标城市为准)
3. 岗位方向:想做什么岗位(如「弱电智能化项目经理」「安防项目经理」「产品经理」等)
4. 薪资底线:能接受的最低月薪(如 15K)
5. 学历与证书:学历(如大专/本科)、已取得的关键证书(如一级建造师、PMP、HCIP)
6. 语言能力:是否有语言限制(如「不能接受英语作为工作语言」「粤语只会听」)
7. 出差限制:是否接受出差、外派、海外驻场
8. 企业偏好:重点想去的企业或企业类型(如国企/央企/大厂/上市公司/物业龙头)
9. 简历:主动提醒用户「可以上传简历(PDF/Word),我会自动解析你的经验、证书、项目经历,筛选更精准」。若用户上传简历,先解析提取关键信息(经验年限、证书、项目方向、地点),与上述字段合并。
如果关键信息缺失(如不知道目标城市、没说薪资底线),先补问再继续;用户明确说「随便/你看着办」时才用合理默认值,并在交付时说明假设。
第 2 步:联网搜索岗位
用搜索能力在以下平台搜索用户岗位方向的新岗位:
- 猎聘(liepin.com / m.liepin.com)
- BOSS直聘(zhipin.com)
- 智联招聘(zhaopin.com)
- 前程无忧(51job.com)
- 筑招网(zhupinhr.com)等建筑/工程垂直平台
搜索要点:
- 关键词用「岗位方向 + 城市」,如「杭州 电商运营专员」——岗位方向与城市按用户画像代入,不局限于本示例
- 尽量抓取岗位详情页 URL(格式如 https://m.liepin.com/job/{id}.shtml、https://m.zhipin.com/job_detail/{code}.html),避免用列表页/搜索页 URL
- 若某平台详情页不开放(如部分 BOSS 岗位),可先用该岗位的搜索结果页兜底并在推荐理由中注明,让用户决定
- 记录每个岗位:标题、公司、薪资、区域、经验要求、学历要求、平台、发布时间、职位描述
- 【必做】猎聘详情页的「相似岗位推荐位」要一并扫描:匿名岗位(显示「某XX公司」)的详情页 WebFetch 常常拿不到 JD 正文,但返回值里的相似岗位推荐区块会暴露一批真实岗位的完整信息(公司名 + 薪资 + 区域 + 学历 + 详情页链接)。这是高价值岗位的重要来源——实测曾由此挖到「某央企商业地产·智能化管理岗(核心区·20-25K×16薪·当日更新)」这类清单里搜不到的岗位。每次 WebFetch 猎聘详情页都必须扫推荐位,不能只看目标岗位正文
- 【必做】按「公司名」直搜,不能只靠岗位关键词:猎聘对中型企业(100-1000 人、专精特新、区域工程龙头)严重漏网——实测某公司官网在招 43 个岗位,猎聘一条都搜不到。中型企业发岗主阵地在 BOSS直聘 + 智联/前程无忧。搜索时必须按公司名直搜,关键词同时换成「售前方案经理 / 投标经理 / 工程主管」等同义岗位名
- 薪资字段缺失时的交叉验证源:quanzhi.com(全职招聘网)、tanzhi.cn、qixin.com(启信宝)、jobui.com 可补齐猎聘/智联缺失的薪资。⚠️警惕历史旧数据:启信宝等平台常显示几年前的历史招聘信息(实测某公司显示为 2020 年数据),必须核对发布日期后再采用;同一公司在不同平台薪资口径可能不同,以最新更新的平台为准
- 平台反爬与可达性(⚠️ 2026-09-03 实测复盘,必须按渠道分策略,禁止因难抓就长期不更新某渠道):
- 猎聘 liepin.com / m.liepin.com:WebFetch 全程畅通(列表+详情),维持主源。
- 智联 zhaopin.com:⚠️ 历史版本误判为「整体被安全验证拦截」——这是上一轮漏掉智联的根因。实测列表/搜索页(sou.zhaopin.com、zhaopin.com/shenzhen/...)WebFetch 完全可抓,能拿到岗位名/公司/薪资/区域/经验学历/详情页链接;仅详情页(zhaopin.com/jobdetail/...)频繁访问会触发频率验证墙(实测 4 个里约 3 个返回「请勾选验证」)。在招确认两条路:① 列表页含「招聘者在线/今日活跃/立即沟通」信号的,直接视为在招;② 详情页二次核实用 agent-browser 真实浏览器(带 JS+cookie,自动过验证墙)。智联须作为与猎聘并列的常驻源,禁止跳过。
- 前程无忧 51job.com(= 51job,同一家):⚠️ 阿里云 WAF(acw_tc)硬反爬,但已实测可突破。现象:WebFetch / 无头 Chrome / 直连 JSON 接口 / 直接 driver.get 旧版 search.51job.com/list 搜索 URL,全部返回 200 OK 空 body(仅 acw_tc cookie、无 acw_sc__v2)——根因是直接打搜索列表 URL 没有 Referer 被 WAF 静默丢弃,且旧版 search.51job.com/list 是被最严规则把守的壳页。✅ 实测唯一可行路径 = 真实搜索流程(见下「浏览器会话抓取」第 3 点「51job 正确打开方式」):用 Selenium + 反指纹补丁(excludeSwitches=enable-automation + AutomationControlled 关闭 + 覆盖 navigator.webdriver)起有头 Chrome,先逛首页 www.51job.com 建立会话 cookie,再从首页搜索框输入关键词回车提交(自带 Referer),页面跳转到新版 we.51job.com/pc/search 即正常渲染真实岗位。岗位数据在每个 .joblist-item 的 sensorsdata 属性(JSON:jobId/jobTitle/jobSalary/jobArea/jobYear/jobDegree/jobTime),公司名在 .cname 的 title;详情链接 https://we.51job.com/pc/job/{jobId}。禁止再写「51job 不可自动化」——那是早期误判,现已实证可抓 20+ 真实在招岗位。
- BOSS直聘 zhipin.com:⚠️ 直接 WebFetch 详情页无解——www.zhipin.com/job_detail/ 返回登录墙、m.zhipin.com 返回 IP 安全验证(⚠️ 2026-09-15 双实测,外部方案声称「m.zhipin.com 无需登录」经核实为假,勿再轻信)。但 WebSearch site:zhipin.com 关键词 城市 完全可用:搜索结果摘要自带薪资/区域/学历/经验/JD 原文与真实详情页 URL(zhipin.com/job_detail/{code}.html),是无登录会话时 BOSS 渠道的唯一初筛通道。使用约束:① 摘要数据可入库但必须标「投递前确认」;② 汇报中注明「BOSS 数据来自搜索摘要,时效以用户点开详情页为准」;③ 摘要里没有的字段(HR 在线状态等)留空,禁止脑补;④ 有已登录浏览器会话时仍走下方 CDP 路径拿实时数据;⑤ ⚠️ 摘要可能张冠李戴——实测搜某深圳科技公司名,返回的智联详情页实为上海另一家公司(2026-09-15 实证),摘要中的公司名/岗位与 URL 的对应关系不可全信,入库前必须打开详情页核实公司与岗位一致性,对不上的禁止入库。同样的 site: 搜索法可作为所有平台的初筛/交叉验证补充(如 site:liepin.com、site:zhaopin.com)
- 【必做】猎聘搜索参数用 city=城市代码:列表页 URL 格式 https://www.liepin.com/zhaopin/?key=关键词&city={代码}(示例:深圳=640)。⚠️ 实测 dq= 参数返回空结果(2026-09-15 复盘:一轮搜索因用 dq 参数全部报空,浪费时间);移动版 m.liepin.com/zhaopin/?key=...&cityCode={代码} 亦可用。其他城市先查平台城市代码表再拼 URL。关键词矩阵至少覆盖:岗位方向词(按用户画像的方向)+ 方向扩展词(相邻领域词)+ 同义岗位名(如「售前方案经理/投标经理/工程主管」这类同义变体)
- 【必做】智联公司主页突破法(列表页信息不全时的钥匙):sou.zhaopin.com 搜索列表页常出现薪资隐藏、详情页链接不展示的岗位(只能看到公司名与岗位名)。此时 WebFetch 该公司的主页 https://www.zhaopin.com/companydetail/CZxxxxxx.htm(CZ 编号可从列表页或搜索结果获得),即可拿到全部在招职位的完整列表:岗位名 + 薪资 + 区域 + jobdetail 详情页 URL。实测由此挖出某头部物业科技公司 700+ 在招岗中的方案岗、某楼宇科技公司 22 个在招岗(关键词搜索一条都搜不到的目标企业)。目标企业在智联有主页的,优先走这条路
- 【2026-09-15 实证更新】智联详情页可达性:CC 格式详情页(zhaopin.com/jobdetail/CCxxx...htm)与移动版(m.zhaopin.com/jobs/CCxxx...htm)WebFetch 多数可直接打开,不必预设被验证墙拦截——先直开核实,失败再用「公司主页」或跨平台交叉验证兜底。v1.5.0「详情页频繁触发验证墙」的说法以本条为准修正
- 51job / 全职招聘网详情页实况(2026-09-07/15 实证):msearch.51job.com/jobs/{城市缩写}/{jobId}.html 与 we.51job.com/pc/job/{jobId} 详情页 WebFetch 可正常核实;quanzhi.com 已确认返回 418 反爬,不要再依赖,薪资缺失时改用 jobui.com / tanzhi.cn / 最新更新的平台口径
- 51job / BOSS 唯一可行路径 = 已登录浏览器会话:需在本机固定目录预留专用 Chrome profile(如 %USERPROFILE%\job-catcher-profile,含 Login Data / Network / Local Storage 会话数据位;首次使用时创建)。① 用户先在本机用该 profile 对 51job、BOSS 各登录一次(命令见下方「浏览器会话抓取」);② 后续更新用 agent-browser 或同 profile 的 Chrome 加载岗位页抓取。无登录会话时这俩渠道本期 0 新增属正常,交付报告须显式说明「51job/BOSS 待你完成一次登录后开启」,不得假装已覆盖。
- 【企业清单路线·拓企策略(2026-09-15 沉淀,搜岗的另一条路)】:除了按岗位关键词搜,还可以先按「三类好公司」方法论建立目标企业清单,再按公司名反查在招岗位:
1. 杰出雇主榜单(Top Employers Institute 年度认证企业):官方公布认证名单(如 2026 中国区 168 家),这类企业福利制度经第三方审计(双休/年假/商业保险),是「钱多事少」首选池
2. 专精特新名单:各地工信部门官方公示(如深圳 2025 公示 2536 家,可按区/行业筛选),稳定性和成长性双背书
3. 细分行业龙头:注册资本 500 万以上 + 客户是行业巨头 + 名气不大利润高的小众品牌(用户可在企查查/天眼查按此标准筛选本市企业) - 执行链路:名单 → 筛出与用户行业域相关的企业 → 工商源核实(参保人数/注册资本实缴/减资等经营信号——招聘平台的规模口径可能差 10 倍,以工商为准)→ 按公司名直搜各平台在招岗位
- 实证效果:由此挖到关键词搜索完全覆盖不到的某央企地产系企业岗、并确认某头部物业公司持有杰出雇主认证背书;注意名单中企业也可能全部无对口岗(正常,列入每周复查蹲守即可)
第 3 步:严格过滤(按用户画像)
逐条岗位对照用户画像过滤,任何一条不满足就剔除或降级:
1. 地点:必须落在用户可接受的区域;写「全国调配/服从调动」的岗位要提示
2. 薪资(🔴 2026-09-03 用户放宽,以此版为准):看上限不看下限——只要岗位的薪资上限 ≥ 用户薪资底线,即判定合格。如用户底线 15K,则 1-1.5万、1.2-1.8万、1.1-2万、9千-1.5万 全部合格;只有上限 < 15K 的(如 8千-1.2万、6-10K)才过滤。写年薪的换算成月薪再比上限。<br>⚠️ 旧规则「薪资下限必须 ≥ 底线」已于实测中作废,切勿再用下限过滤,否则会误杀大量合格岗位(实测因此漏掉某本地科技公司 3 个大专可投岗位)
3. 学历:用户学历不满足的岗位直接排除(如要求统招本科但用户无学位证);「学历不限/大专可投」优先
4. 语言:要求英语作为工作语言、要求粤语熟练的岗位排除
5. 出差:长期海外驻场/长期出差的岗位排除或重点标注提示
6. 时效(🔴 2026-09-15 用户确认口径):详情页显示「X天前更新」≥90天 → 直接剔除,不允许"标注保留"。唯一例外:岗位虽挂网超90天,但详情页/列表页显示近期仍在刷新(如"今日更新""3天前更新")→ 保留并在 publishDate 标注刷新日期。判定以详情页展示的更新时间为准,不是首次发布时间
7. 方向(🔴 强化:先判行业域,再判岗位形态):目标岗位的产品/业务域必须落在用户画像/简历中声明的经验域内或有直接交集,否则不入池——即使岗位形态(售前/PM/方案)看起来完全匹配。⚠️ 实证教训(某协作机械臂公司售前岗误筛):岗位形式相似≠匹配,售前岗的产品知识=核心能力,跨行业(如机器人/工业自动化/物流仓储自动化)的知识缺口无法"速补",且此类岗位优先条件通常偏好行业内公司(如某头部机器人厂商/某仓储自动化头部),实际竞争者是行业内老兵。"够一够"的能力缺口仅限同行业/相邻行业内的子系统缺口(如熟悉安防但不熟会议系统),不适用于跨行业产品域缺口
8. 去重:同一公司同一岗位视为重复;同一岗位多平台发布保留信息更全的一条
9. 在招状态核实(新增岗位与存量同标准,必须逐个先核实):对所有进入清单的岗位(含当日新搜索到的岗位)必须先 WebFetch 打开详情页核实招聘状态,确认在招才允许加入——
- 页面明确显示「停止招聘 / 已结束 / 已关闭 / 已下线」或原链接已失效(跳转到推荐页/职位不存在)的岗位必须剔除,绝不允许带「待确认」标签入库
- 新增岗位禁止「搜到就入库」:必须先在招状态核实通过才加入;智联详情页常被安全验证拦截,此时用「公司名 + 岗位名 + 城市」在其他平台(前程无忧 / 猎聘 / 全职招聘网 / BOSS)交叉搜索,能找到同岗位在招信息即视为在招
- 交叉验证仍无法确认(各平台均拦截/无结果)的岗位,保留但标注「投递前确认」(不得计入「已核实」统计),并在交付报告中单列,提示用户投递前电话确认
- 核实过程与结论记入交付报告(如「已核实 N 个在招、剔除 M 个已关闭、K 个待确认」)
10. 过滤掉的岗位必须显式汇报,尤其是「差一点」案例:不要静默过滤。当某岗位除一项硬指标外全部命中(如:区域/学历/技术栈/证书全对口,唯独薪资略低于底线),必须在交付报告里单列该岗位 + 明确写出是哪一项不达标 + 说明其余命中项,把决定权交回用户(用户可能愿意为高匹配度放低某条标准)。交付报告应包含一张「本轮剔除清单」表,逐条写明剔除原因(卡统招 / 区域不符 / 薪资不足 / 技术栈不符 / 已关闭等)
第 4 步:生成 HTML 岗位追踪页
将过滤后的岗位整理为 JSON 数组,调用脚本生成 HTML。两种模式:
模式 A:增量合并(🔴 推荐,默认用这个——降 token 消耗)
每轮只把新增 + 本轮字段有变化的岗位写进 delta 文件(存量岗位不需要重写),脚本自动完成合并→去重→时效过滤→生成→落盘:
python3 scripts/build_html.py --jobs 岗位数据_工作捕手_v14.json --merge 岗位增量_v15.json \
--profile 用户画像_工作捕手.json --output 岗位追踪_工作捕手_v15.html --dump-json 岗位数据_工作捕手_v15.json
- delta 文件里的岗位按「id 或 公司名+岗位名」匹配旧数据:命中则只更新提供的非空字段(如本轮复核结论、薪资变化),没命中的作为新岗位入库(
addedDate自动补、缺 id 自动生成稳定 id) --dump-json把合并后的完整数组落盘,下一轮直接作为--jobs输入,形成闭环- 脚本自动做三件事:① 同公司同岗位去重(保留字段更全的);② delta 中猎聘发布超 90 天的新岗位自动剔除并打印原因(时效闸门只管新入库,存量岗位的去留由每轮复核决定);③ 必填字段校验(漏字段会报错退出,不会生成残缺页面)
- 合并是幂等的:同一 delta 误跑两遍不会产生重复岗位
模式 B:全量模式(旧用法,仅在没有旧 JSON 需要初始化时用)
python3 scripts/build_html.py --jobs 岗位数据.json --profile 用户画像.json --output 岗位追踪.html
岗位 JSON 字段(每个岗位必须包含):
{
"id": "唯一英文id(公司-岗位名,如 dashi-zhineng)",
"title": "岗位名称",
"company": "公司名称",
"salary": "薪资,如 15-20K",
"area": "区域,如 南山区·科技园",
"experience": "经验要求,如 5-10年",
"education": "学历要求,如 大专/本科",
"platform": "来源平台,如 猎聘",
"companyType": "企业类型,如 上市公司/国企",
"publishDate": "发布时间",
"description": "职位描述(1-3句)",
"matchLevel": "匹配度:高 / 中高 / 中",
"matchReason": "推荐理由(结合用户画像说明为什么匹配)",
"url": "岗位详情页链接",
"focusCompany": true,
"addedDate": "今日日期 YYYY-MM-DD"
}
用户画像 JSON 字段(profile)——示例值为虚拟人物「王小明」,使用时按真实用户画像填写:
{
"name": "用户姓名/称呼(如 王小明)",
"title": "页面 title(如 杭州电商运营岗位追踪)",
"headerTitle": "页面头部大标题(如 🌿 杭州电商运营 / 数字化营销岗位追踪)",
"sub": "副标题(如 电商运营 · 用户增长 · 数据分析 | 运营经理方向)",
"userLine": "用户信息行(如 👋 王小明 💼 5年电商运营经验 🏅 数据分析·CET-4)",
"experience": "经验描述",
"certificates": "证书",
"salaryRule": "薪资判定规则,默认「上限≥底线即合格」(如「上限≥12K即纳入,仅上限<12K过滤」)",
"acceptedAreas": "可接受区域清单(如「仅西湖区/滨江区/余杭区,其余区通勤长不推」)",
"educationConstraint": "学历约束(按用户实际学历填写,如「要求985/211的岗位不投;学历不限/大专可投优先」)",
"techBlacklist": "技术栈黑名单(用户不熟悉且 JD 实质要求的技能,如「直播带货/供应链管理——JD实质要求这些的岗位一律过滤」)",
"certPhrasing": "证书表述规范(如「打招呼用语中证书按官方全称写,不写简称或未持有的方向」)"
}
⚠️ 画像即隐私:profile 含用户姓名、区域、薪资、学历等敏感信息,只存于用户本地工作区,严禁写入技能包、公网页面元数据或交付给第三方。
增量更新固定流程(用户说「更新岗位清单」时按此执行):
1. 读取现有最新版 岗位数据_工作捕手_vN.json,逐个 WebFetch 详情页复核存量岗位在招状态——复核只记结论(在招/已关闭/字段变化),不要重写岗位全文。⚠️ 复核 prompt 必须显式要求提取详情页的「更新时间」字段(如"90天前更新/3天前更新/今日更新")——2026-09-15 实证教训:某小公司售前岗复核时只记了"在招+HR在线",漏记了页面上的"90天前更新"时效信号,导致超时效岗位以正常状态混在清单里被用户截图指出。复核发现更新时间≥90天且无近期刷新的,走第 5 步 --remove 剔除
2. 按第 2 步搜索矩阵扫新岗(猎聘 city=城市代码 关键词矩阵 + 智联列表页/公司主页 + BOSS site: 摘要 + 51job 详情页)
3. 按第 3 步 12 条规则过滤,在招核实通过才入库
4. 只写增量 delta 文件 岗位增量_v{N+1}.json:内容 = 新岗位 + 本轮结论有变化的存量岗位(仅提供变化的字段,如 verifiedActive、新薪资),文件末尾附一行注明剔除岗位清单(脚本生成的剔除以脚本输出为准)
5. 一条命令完成合并与生成(需剔除存量岗位时加 --remove "id1,id2,..."):
python scripts/build_html.py --jobs 岗位数据_工作捕手_vN.json --merge 岗位增量_v{N+1}.json --remove "id1,id2" --profile 用户画像_工作捕手.json --output 岗位追踪_工作捕手_v{N+1}.html --dump-json 岗位数据_工作捕手_v{N+1}.json
(版本号递增不覆盖旧版;--dump-json 落盘的文件即下一轮的输入;--remove 按逗号分隔 id 精确剔除并打印剔除明细,id 写错会显式警告)
6. 同步部署目录:cp 岗位追踪_工作捕手_v{N+1}.html job-catcher-deploy/index.html(部署目录名由用户自定,保持固定即可)
7. 汇报:总数变化(N→M)、新增岗位表、剔除清单(含原因)、「差一点」案例单列
降耗原则:搜索与详情核实(WebSearch/WebFetch)是必要消耗,无法省;但岗位数据写入必须走 delta 增量,禁止每轮重写全量 JSON——存量 20+ 岗位全文重写每轮要多消耗数千 token,增量模式只写变化项,token 消耗随变化量而非总池大小增长。
第 5 步:交付
- 向用户交付生成的 HTML 文件(用 computer:// 协议发送文件绝对路径)
- 汇报:本次共 N 个岗位,其中重点企业 X 个、高匹配 Y 个;说明过滤掉的不符合条件的岗位数量(含已关闭岗位剔除数量)
- 提醒用户:可每天/隔天让技能再次运行,把新岗位追加进同一份 HTML(保留原有岗位和投递状态)
第 6 步:公网部署(跨设备访问,推荐)
本地 file:// 路径只能在当前电脑打开。如需转发到手机/其他终端查看,将 HTML 部署为公网链接:
- htmlcode.fun(单页快发):python scripts/htmlcode_deploy.py deploy 页面.html --title "标题" --description "一句话说明"。注意该服务有发布额度,返回 402 时改用 CloudStudio
- CloudStudio(静态托管,需含 index.html 的目录):把 HTML 复制为 deploy-dir/index.html,用内置 CloudStudio 部署工具发布目录,获得公网分享链接。同一部署目录重复部署会复用同一链接,适合每日刷新场景
- 部署后验证:WebFetch 公网 URL,确认岗位数量正确、字段无 undefined。CloudStudio 等平台有 CDN 缓存,刚更新后若仍显示旧内容,给 URL 加 ?v=时间戳 参数穿透缓存复验
- 交付时同时给出公网链接;若部署返回的链接与之前不同,必须显式告知用户链接已变化
浏览器会话抓取(51job / BOSS 必需,其余渠道不需要)
51job / BOSS 服务端对无会话/无头请求返回空/登录墙,纯 WebFetch 无解。环境已预留专用 Chrome profile(含会话数据位),用真实有头(headed)Chrome 复用该 profile 即可突破无头检测。经实测沉淀以下可行流程与坑:
1) 一次性登录(用户在本机执行,需显示器 + 其账号):
:: 用专用 profile 启动有头 Chrome 并开调试端口,分别打开 51job / BOSS 登录页,手动登录一次
:: 路径按本机 Chrome 安装位置与所选 profile 目录调整(profile 目录需固定,登录后勿清除)
"chrome.exe完整路径" --remote-debugging-port=9223 --user-data-dir="%USERPROFILE%\job-catcher-profile" "https://www.51job.com" "https://www.zhipin.com/web/geek/job?query=岗位关键词&city=城市代码"
登录后不要清空该 profile。会话 cookie 持久化在磁盘,重启用同 profile 仍保持登录(已验证:窗口关掉后重开 BOSS 仍在线)。
2) 自动化抓取(已验证可行 = 有头 Chrome + CDP):用 Node ws 模块连 ws://127.0.0.1:9223,抽取脚本(如 cdp_extract.js 与注入函数 extract_fn.js)需自备并放在本机 Node 工作目录(路径因环境而异,本技能包不附带)。核心步骤:① Page.enable+Runtime.enable;② 选与目标同 host 的已有 page tab(新建 tab 用 CDP Target.createTarget,/json/new 受「unsafe devtools」保护会报 Using unsafely reachable devtools server 不能用);③ 若 tab 已是结果页则不要重复 Page.navigate(reload 会触发 chrome-error://chromewebdata/ 错误页),直接等 SPA 渲染;④ 等 Page.loadEventFired 后再 Runtime.evaluate。抽取函数源码独立放 extract_fn.js 用 JSON.stringify 安全注入,禁止在模板字符串里手写字面量正则(曾因 \/ 转义产生 SyntaxError: Unexpected token ')')。
⚠️ 三个实测坑(必看):
- Runtime.evaluate 返回值是双层嵌套:结构是 response.result.result.value,脚本里务必用 ev.result.result.value;只取一层 ev.result.value 会得到 undefined(曾因此误判「BOSS 无数据」)。
- BOSS _security_check 风险校验:账号级风控,URL 带 _security_check=1_xxx 时列表被 withholding、仅返 1 张卡片。这是人工验证闸门,不是技术墙——禁止尝试代码绕过验证码;正确解法是请用户在该有头窗口内完成验证(点验证/滑块),再重跑抽取。
- 51job 服务端空 body:即便有头 Chrome + 已登录 profile,search 列表页 bodyLen:0、标题为空(与 WebFetch 空 body 同源)。非登录墙(不跳转登录页),是服务端内容抑制;目前不可自动化绕过,交付须显式标注「51job 待人工浏览器浏览 / 粘贴链接」。
3) 51job 正确打开方式(✅ 2026-09-03 实测可抓,20+ 真实在招岗位):
- 根因:51job 是阿里云 WAF(acw_tc)。直接 driver.get('search.51job.com/list/...') 或 WebFetch/无头/直连接口,WAF 因「无 Referer + 旧版壳页」静默返回空 body(只有 acw_tc、没有 acw_sc__v2),不是登录墙、也不是永久不可破。
- ✅ 正确流程(Selenium + 反指纹,脚本需自备并放在本机 Python 工作目录,本技能包不附带):
1. 用 Selenium 4 起有头 Chrome,加反指纹补丁:options.add_experimental_option('excludeSwitches',['enable-automation']) + options.add_argument('--disable-blink-features=AutomationControlled') + driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {source:'Object.defineProperty(navigator,"webdriver",{get:()=>undefined})'});selenium 依赖装在隔离 Python venv(venv 路径由用户环境自定,勿装全局)。
2. 先 get('https://www.51job.com') 逛首页建立会话 cookie(首页 WAF 轻,能正常返回)。
3. 在首页搜索框(.search-input input)输入关键词、回车提交——走真实用户搜索流程、自带 Referer,页面跳到新版 we.51job.com/pc/search?keyword=...&jobArea=040000 即正常渲染。
4. 等 .joblist-item 出现;每个卡片数据在 sensorsdata 属性(JSON:jobId/jobTitle/jobSalary/jobArea/jobYear/jobDegree/jobTime),公司名在 .cname 的 title;详情链接 https://we.51job.com/pc/job/{jobId}。
5. ⚠️ 不要用 get 直打旧版 search.51job.com/list、不要无头、不要 WebFetch——这三路必空。
- BOSS 仍走第 2 点 CDP/登录会话路径(_security_check 人工验证闸门需用户点一下)。
兜底与弃用:agent-browser 仅适合简单 snapshot;--headless=new --dump-dom 对 51job/BOSS 均被识破返回空,51job 必须走上面的真实搜索流程(有头+Referer),BOSS 必须 headed+登录。
匹配度分级
- 高:地点+薪资+学历+方向全部满足,且经验/证书强相关
- 中高:基本满足,个别条件需确认(如学历标注「学位待确认」、方向略有偏差)
- 中:薪资或方向部分满足,或有明显需注意的点(如出差提示、公司规模小)
- ⚠️ 行业域判定优先于上述分级:产品域跨行业的岗位无论形态多匹配,最高只能标「中」且必须写明「跨行业·仅练手」,或直接不入池(见第 3 步规则 7)
重点企业标注
用户画像中的偏好企业/企业类型,命中则 focusCompany: true(页面显示 ⭐重点企业)。
边界情况
- 搜索结果太少(<3 个):优先换平台(BOSS/前程无忧/智联)与换关键词(同义岗位名、按公司名直搜)扩大池子;确实需要放宽时,方向优先放「相邻区域」或「时效(90 天略放宽)」,并在交付时说明放宽了什么。⚠️ 薪资不要再做下限下探——第 3 步已改为看上限,继续按下限过滤属于误杀
- 完全没有符合的岗位:如实说明,不要编造岗位
- 岗位链接打不开/不开放:保留岗位但注明链接情况,让用户决定是否保留
- 用户画像信息冲突:以用户最新表述为准
重要原则
- 岗位信息必须来自真实搜索,禁止编造公司、薪资、链接
- 详情页链接优先,列表页兜底必须注明
- 生成 HTML 用脚本,不要手写重复页面
- 页面风格保持浅色清新(薄荷绿/天蓝),不要让求职者觉得压抑
每日自动更新(可选)
本技能支持封装为定时自动化任务,实现每日自动刷新岗位清单:
- 任务 prompt 需自包含:用户画像、搜索关键词矩阵、过滤规则(含在招状态核实)、本地文件路径、生成脚本路径、部署目录与公网链接一致性校验要求
- 推荐调度:每天上午(如 10:00)执行
- 执行链路:搜索新岗 → 硬性过滤 → 核实存量岗位在招状态 → 更新岗位 JSON → 重新生成 HTML → 覆盖部署目录 → 重新部署 → 带 ?v= 验证 → 输出中文日报(新增/过滤/总数/链接是否变化)
更新记录
v2.3.0(2026-09-15,隐私清理 + 虚拟示例 + 品牌定稿「工作捕手」)
- 🔴 隐私清理(发布前必读):全包扫描并移除真实个人信息——本机绝对路径(Chrome profile / CDP 脚本 / venv,含用户目录名)全部改为通用写法(
%USERPROFILE%\job-catcher-profile等);用户真实画像示例值(目标区域/薪资/学历约束/证书表述)替换为虚拟人物「王小明(杭州·电商运营方向)」;实证案例中的真实公司名全部匿名化(某央企商业地产/某头部物业科技公司/某协作机器人公司等);新增「画像即隐私」条款——profile 只存用户本地,严禁写入技能包与公网页面元数据 - 品牌定稿:中文名「工作捕手 · 自动追踪岗位清单」+ 调用名
job-offer-radar;示例文件名与部署目录统一为岗位数据_工作捕手_vN.json/job-catcher-deploy - 脚本品牌统一:build_html.py 横幅与描述改为「工作捕手」
v2.2.0(2026-09-15,改名 + 说明重写 + 策略沉淀)
- 改名:
offer-radar→job-offer-radar(job + offer 双高频搜索词命中;frontmatter name 可独立于目录名修改,目录保留 offer-radar 不动以维持历史路径引用) - 中文品牌名(用户创意采纳):「工作捕手 · 自动追踪岗位清单」作为品牌名置于 description 首位与正文标题;调用名保持 job-offer-radar(slug 承担搜索命中,中文品牌承担记忆点,两者互补);「工作捕手/自动追踪岗位」加入 trigger_keywords;页面 title 不跟改——storage key 按画像 name+title 生成,改标题会清零用户已标记的投递状态
- description 全量重写:面向「被更多人搜到」优化——开头一句话说清能做什么,正文列 6 项能力(真实岗位核实/硬过滤/追踪页/匹配度+打招呼用语/增量更新/企业拓企),塞入找工作/求职/投简历/跳槽/转岗/岗位推荐/打招呼用语/匹配度分析等高频触发词;tags 扩充至 15 个、trigger_keywords 扩充至 18 个
- 新增「这个技能能帮你做什么」使用者必读章节:6 条能力清单,让新使用者不用读全文就知道技能边界
- 新增(第 2 步)企业清单路线·拓企策略:三类好公司方法论(杰出雇主榜单/专精特新名单/细分行业龙头)→ 行业域筛选 → 工商源核实(参保/注册资本,平台规模口径可差 10 倍以工商为准)→ 按公司名反查在招岗位
- 补强(第 2 步 BOSS site: 约束⑤):搜索摘要可能张冠李戴(实测搜某深圳科技公司名,返回的智联详情页实为上海另一家公司),公司/岗位与 URL 对应关系入库前必须开详情页核实
v2.1.1(2026-09-15,90天时效口径收紧 + --remove 剔除能力)
- 🔴 事故复盘:某小公司·售前岗(10-15K)详情页显示「90天前更新」,入库复核时只记了"在招+HR在线"、漏记时效信号,超时效岗位以正常状态混入清单被用户截图指出
- 口径收紧(第 3 步规则 6,用户确认):详情页「X天前更新」≥90天 → 一律直接剔除,废除此前"卡线岗位保留+标注投前确认"的违规执行;唯一例外=挂网超90天但近期仍在刷新(如"今日更新")→ 保留并标注刷新日期
- 存量集中清理:按新口径一次性剔除 7 岗(全部为「90天卡线」岗位),保留 1 个"超90天但当日刷新"的活跃岗,25 → 18 岗
- 脚本 build_html.py 升 2.1.1:新增
--remove "id1,id2,..."(按 id 精确剔除存量岗位,打印剔除明细,id 未命中显式警告)——补齐增量流程的删除能力 - 复核规则强化(固定流程第 1 步):复核 prompt 必须显式要求提取详情页「更新时间」字段,杜绝再次漏记时效信号
v2.1.0(2026-09-15,吸收 TRAE 重打包方案)
- 来源:用户提供的 TRAE 重打包技能包(offer-radar-skill.zip,含 SKILL.md + update-jobs.js + template.html + Surge.sh 配置),逐项核实后有取舍地吸收
- 🔴 新增(第 2 步)BOSS site: 搜索初筛通道:TRAE 声称「m.zhipin.com WebFetch 无需登录」,实测为假(www=登录墙、m.=IP 安全验证,2026-09-15 双实测)——但其 WebSearch
site:zhipin.com 关键词 城市路线成立:搜索摘要自带薪资/区域/学历/JD 原文与真实详情页 URL。吸收为「无登录会话时 BOSS 的唯一初筛通道」,附四条使用约束(标投递前确认/注明摘要时效/缺字段留空禁脑补/有会话仍走 CDP)。修正原「BOSS 登录墙=完全无解」的绝对化表述 - 🔴 新增(第 4 步)脚本增量合并能力(核心降耗):build_html.py 升级 2.1.0,新增
--merge delta.json(按 id 或 公司名+岗位名 合并,命中只更新非空字段,新增自动补 addedDate/稳定 id)、--dump-json(合并结果落盘供下轮闭环输入)、自动去重(公司+岗位保留字段更全者)、新岗位 90 天时效闸门(只管 delta 入库,存量去留仍由每轮复核决定,脚本不越权)。TRAE 的 update-jobs.js 采用「从生成 HTML 里正则反抽旧数据」的脆弱设计,未采用;改为 JSON 文件直读+落盘闭环。幂等性已冒烟验证(同 delta 跑两遍 25 岗不增重复) - 新增(增量更新固定流程)降耗原则:存量复核只记结论不重写全文;岗位数据写入必须走 delta 增量,token 消耗随变化量而非总池大小增长
- 不吸收(附原因):① Surge.sh 部署——需注册第三方账号,用户已有 CloudStudio/发布为应用链路且同目录复用链接;② salary-lookup.json 薪资查表缓存——我们的薪资在搜索/核实阶段即已拿到,该缓存是为「BOSS 摘要无薪资」场景设计的绕路方案,非最优解;③ TRAE 的多轮对话画像收集模板——用户画像已固化在工作区的 用户画像_工作捕手.json,重复设计
- 冒烟验证:v14(24岗)+ delta 3(1更新/1新增/1超90天剔除)→ 25 岗,校验/生成/落盘/幂等全部通过,测试文件已清理
v2.0.0(2026-09-15,多轮改进汇总重打包)
- 新增(第 2 步):猎聘搜索参数固化
city=640(dq=640实测返回空,禁用);移动版 cityCode=640 可用 - 新增(第 2 步):智联公司主页突破法——列表页薪资/详情链接隐藏时,WebFetch
zhaopin.com/companydetail/CZxxx.htm拿全部在招职位+jobdetail 链接(实测挖出某头部物业科技公司 722 岗、某楼宇科技公司 22 岗) - 修正(第 2 步):智联详情页可达性——CC 格式 jobdetail / m.zhaopin.com/jobs 多数可直开,先直开再兜底,替代 v1.5.0「详情页普遍被验证墙拦截」的旧印象
- 新增(第 2 步):51job 详情页(msearch.51job.com / we.51job.com/pc/job)WebFetch 可核实;quanzhi.com 已 418 反爬,移出交叉验证源
- 新增(第 3 步规则 11):技术栈黑名单过滤(profile.techBlacklist)+ IDC 运维岗陷阱(高薪 IDC/动环岗与「数字全中、方向不对」变形岗的识别判据=JD 任职要求第 1-2 条)
- 新增(第 3 步规则 12):🔴 链接铁律——入库 URL 必须详情页,列表页特征(/zhaopin/?key=、/city-sz/、sou.zhaopin.com 等)一律退回重取,输出前强制校验
- 新增(第 4 步):profile 扩展字段(salaryRule / acceptedAreas / educationConstraint / techBlacklist / certPhrasing);固化「增量更新固定流程」7 步与文件版本化命名(岗位数据_vN.json → v{N+1}.json 不覆盖旧版)
- 新增(第 3 步规则 10):「差一点」岗位连续 ≥2 轮未表态的,后续只保留剔除清单一行,不再展开
- 涉及文件:
SKILL.md(本文件重打包);模板时区修复(getLocalToday)此前已同步至templates/job_tracker_template.html
v1.8.0(2026-09-08,补记)
- 新增(第 3 步规则 7 强化 + 匹配度分级):跨行业产品域缺口岗位不入池——先判行业域,再判岗位形态;产品域必须落在用户画像声明的经验域内。实证教训:某协作机器人公司售前岗形态全命中但属机器人/工业自动化行业,误筛后剔除;「够一够」仅适用于同/相邻行业内的子系统知识缺口
- 新增(第 3 步规则 2):薪资口径明确为「上限 ≥ 底线」规则的执行细节与年薪换算说明
v1.7.0(2026-09-03)
- 纠正 51job「不可自动化」的误判(重大):v1.6.0 写「51job 服务端空 body、不可自动化绕过」是错的。实测根因是阿里云 WAF(
acw_tc)对「无 Referer 直打旧版 search.51job.com/list」静默返回空壳,且旧版列表页是被最严规则把守的壳。✅ 已实证突破:Selenium 4 + 反指纹补丁起有头 Chrome,先逛首页建会话、再从首页搜索框回车提交(真实流程+Referer),跳到we.51job.com/pc/search即正常渲染;岗位数据在.joblist-item的sensorsdataJSON,公司名在.cname的title,详情https://we.51job.com/pc/job/{jobId}。脚本uc_51job_final.py已落地,实测抓到 20+ 真实在招岗位并并入清单。 - 新增「51job 正确打开方式」小节:明确禁止无头/WebFetch/直打旧版 list(三路必空),必须「有头 Chrome + 反指纹 + 真实搜索流程」。
v1.6.0(2026-09-03)
- 固化「有头 Chrome + CDP」为 51job/BOSS 唯一验证可行抓取方案:重写「浏览器会话抓取」小节——登录命令加
--remote-debugging-port=9223;抓取改用 Nodews连 9223 的cdp_extract.js(抽取函数extract_fn.js)。 - 新增三处实测坑(防再次踩):①
Runtime.evaluate返回双层嵌套result.result.value,取错层会得undefined;② 已是结果页时禁止重复Page.navigate(reload 触发chrome-error空白页),改为直接等渲染;③ BOSS_security_check是账号级人工验证闸门,不得代码绕过,须请用户在有头窗口完成验证后重跑;51job 有头+登录仍bodyLen:0(服务端内容抑制),不可自动化。 - 弃用:
--headless=new --dump-dom与 agent-browser 对 51job/BOSS 均失效,明确「必须 headed」。
v1.5.0(2026-09-03)
- 🔴 修正重大误判(根因修复):历史版本把智联写成「整体被安全验证拦截」,导致上一轮更新几乎只出猎聘。实测纠正为:智联列表/搜索页 WebFetch 完全可抓,仅详情页有频率验证墙(列表页「招聘者在线/立即沟通」信号即可判定在招)。智联升级为与猎聘并列的常驻源,禁止跳过。
- 新增(反爬事实与解法,带实证):第 2 步补充四平台可达性对照——猎聘畅通 / 智联列表通详情频率墙 / 51job 服务端空 body(WebFetch+接口+无头 Chrome 三路全空)/ BOSS 登录墙。明确 51job 与 BOSS 的唯一可行路径 = 已登录浏览器会话,并给出专用 Chrome profile 路径与一次性登录命令、agent-browser 抓取命令、无头
--dump-dom --virtual-time-budget兜底方案。 - 新增:「浏览器会话抓取」独立小节,固化 51job/BOSS 的登录式抓取流程;明确无会话时这俩渠道 0 新增须显式说明、不得假装已覆盖。
v1.4.0(2026-09-03)
- 🔴 规则变更(重要):第 3 步过滤规则第 2 条薪资判定由「下限 ≥ 底线」改为「上限 ≥ 底线即合格」(用户当日明确放宽)。旧规则会大量误杀:实测仅此一项就漏掉某本地科技公司 3 个「学历达标 + 目标区域 + 上限达标」岗位。同时修正边界情况里「薪资下限略微下探」的过时建议
- 新增:企业目标清单场景——除岗位清单外,用户需要按公司维度建目标企业地图(地址/规模/资质/业务匹配/风险),需交叉核实工商登记(参保人数、注册资本、资质、司法风险)而非只看招聘平台
v1.3.0(2026-09-03)
- 新增(重要):第 2 步「猎聘相似岗位推荐位必扫」——匿名岗位详情页拿不到正文时,推荐位区块会暴露真实岗位完整信息,是最高价值岗位的来源之一,实测曾由此挖到清单搜索完全搜不到的央企甲方岗
- 新增:第 2 步「按公司名直搜」——猎聘对中型企业严重漏网(实测某公司在招 43 岗、猎聘 0 条),必须按公司名直搜 BOSS/智联/前程无忧,并换用同义岗位名
- 新增:第 2 步「薪资交叉验证源」——quanzhi.com / tanzhi.cn / qixin.com / jobui.com 可补缺失薪资,⚠️ 但需核对发布日期防历史旧数据污染;附智联反爬说明
- 新增:第 3 步过滤规则第 10 条「差一点案例必须显式汇报」——禁止静默过滤,除一项硬指标外全命中的岗位须单列说明并把决定权交回用户;交付报告须含「本轮剔除清单」表逐条写明原因
v1.2.0(2026-09-02)
- 强化:在招状态核实规则扩展到「当日新增岗位」——新增岗位禁止「搜到就入库」,必须先 WebFetch 核实详情页在招状态,确认在招才加入;智联安全验证拦截时改用其他平台交叉验证,仍无法确认才标「投递前确认」且不得计入「已核实」统计。彻底堵住「失效岗位带待确认标签混入清单」的漏洞
- 强化:执行链路「核实存量岗位」改为「核实所有岗位(含当日新增)」
v1.1.0(2026-08-26)
- 修复:模板
const JOBS = [{{JOBS_JSON}}];多套一层数组导致页面只显示 1 个岗位、所有字段 undefined 的 bug,已改为const JOBS = {{JOBS_JSON}};(JOBS_JSON 本身已是 JSON 数组字面量,不需要[]包裹) - 新增:过滤规则第 9 条「在招状态核实」——明确停止招聘/已结束/已关闭或链接失效的岗位必须剔除;无法确认的保留并标注「投递前确认」
- 新增:第 6 步「公网部署」——htmlcode.fun / CloudStudio 两种方式,支持跨设备访问;含 CDN 缓存
?v=穿透验证方法;同一部署目录重复部署复用同一链接 - 新增:「每日自动更新」封装说明,可配合定时自动化实现岗位清单每日刷新
- 涉及文件:
templates/job_tracker_template.html(bug 修复)、SKILL.md(规则与流程更新)
v1.0.0
- 初版:画像收集 → 全网搜索 → 严格过滤 → 生成可交互 HTML 岗位追踪页