Job Nest 是一款专为求职者设计的高性能、轻量化跨平台求职标记与决策管理油猴脚本 (Userscript)。
在 MVP 2.0 升级版 中,本项目引入了**“配置驱动引擎 (Config-Driven Engine)”、“Shadow DOM 样式隔离与属性级状态定位”、“防控制台检测无限刷新对抗层”、“最外层嵌套过滤去重的双源解析机制”以及“异步加载脏数据过滤与标签智能分割”**,实现了一流的用户交互体验与强大的反爬改版弹性。
| 🎯 状态跟踪 | 📝 随手记面板 |
|---|---|
|
|
|
| 📤 数据导出 | 🔍 详情解析 |
|
|
| ⚙️ AI 评估配置 | 🤖 AI 智能诊断 |
|
|
- 四维标记状态:支持就地标记岗位为“已看(仅查看)”、“意向(已保存)”、“投递(已投递)”、“拒绝(不感兴趣)”。
- 随手记备忘录:在面板中即时记录通勤距离、面试进展、技术栈要求、薪资细节等。
- 自定义分类标签:允许用户自己打标签(如:
WLB、离家近、外企),并进行高显提示。
- 视觉灰度去噪:对标记为“已查看”或“不感兴趣(已拒绝)”的岗位卡片,自动追加高保真灰度滤镜并调低不透明度,帮助用户在滑动列表时瞬间剔除噪音。
- 就地 Badge 贴纸:对已标记“有意向/已投递”或写过备注的岗位,在列表卡片边缘就地悬浮覆盖轻量级 Badge 贴纸,悬停可直接阅读之前的随手记摘要,避免重复点击。
- 属性级状态定位 (State Decoupling):移除对动态混淆类名查询的依赖,改用固定的自定义 HTML 属性
data-jp-badge="true"和data-jp-gray="true"进行高稳定的生命周期定位与销毁,防范老 Badge 重叠与灰度残留异常。 - 最外层嵌套过滤 (Nested Card Filtering):引入最外层过滤
Parser.getTopLevelCards,通过树节点过滤排除掉所有嵌套在其他卡片容器内部的子卡片节点(如li内部的div),确保每一个卡片自始至终仅被处理一次。
- 脚本中不含任何特定平台的类名硬编码,解析和挂载逻辑完全由
SiteConfig配置文件驱动。支持云端静默热更新(热插拔),当招聘网站大改版时,只需在线修改配置文件的选择器(Selector),客户端即可瞬间恢复,无需重新发布脚本。
- 工作标签正则智能切分 (Smart Tag Split):自动识别节点文本,并基于
/[\s,,|/、\u2022·]+/正则对多段标签大容器或分隔文本进行智能切分与去重平铺呈现,解决了因选择器大容器或分隔文本引起的标签数据粘连混淆。 - 职务描述样式净化与剔除 (JD Tag Clean):在提取纯文本前对目标 DOM 节点进行克隆剔除(剥离其内部夹杂的
<style>和<script>标签),彻底避免局部排版 CSS 样式定义和 JS 脚本规则对职位描述纯正文的数据污染。 - 异步加载防脏数据与增量补全:自动通过
isInvalidDescription屏蔽“加载失败”、“重新加载”等网络延迟占位符。在面板成功挂载后,若监测到 JD 无效,会在 DOM 改变时在后台自动静默补全。
- 双源提取 (Card Priority):当用户在列表页点击卡片时,解析引擎会同时在左侧职位卡片和右侧详情预览框提取数据,基本职位信息(职位名、公司、薪资)优先采用左侧已渲染好的卡片数据进行初始化,实现零延迟瞬间挂载。
- 退避重试 (Retry Polling):如果网络存在 AJAX 时差导致数据慢渲染,重试机制会以退避算法进行十次重试(最大持续 3 秒),并在数据到位后原地填补。
- 原地刷新 (In-Place Update):若预览框已挂载面板且职位 ID 一致,后续重试数据到位时只会原地刷新面板属性,绝不重建 DOM,彻底消除闪退和闪烁感。
- 路由回退劫持:拦截反爬脚本在检测到控制台打开时触发的
history.back()和history.go(-1)强行回退页面操作。 - Location 8秒限频:拦截反爬脚本由于检测控制台而触发的 Location 无限疯狂重刷,提供
8秒冷却保护,保障 Console 顺畅调试。 - Shadow DOM 绝对隔离:基于原生 Web Components + 开启 Shadow DOM (open mode) 渲染,防止反爬脚本查询 DOM 特征和注入样式污染。
- 穿透 Shadow DOM 的源码复制:由于常规 outerHTML 读取不出 Shadow DOM 内部结构,系统编写了递归 DOM 序列化算法,在复制时自动将 shadowRoot 转换为 HTML5 声明式的
<template shadowrootmode="open">标签,实现“所见即所得”的渲染源码复制。 - 调试控制台彩蛋:面板底部版本号连续点击 5 次可滑出独立的系统运行日志浏览器,以红/黄/绿色彩区分日志,并支持一键写入剪贴板(使用特权 API
GM_setClipboard写入,100% 成功率)。 - 完全兼容的 JSON/CSV 导入导出:支持导出为可导入 Notion/Excel 等工具的转义格式数据,并实现对老用户数据的向下兼容。
- 多简历管理库:支持添加、编辑、删除和选择多个不同版本的 Markdown 格式简历,满足求职者投递不同技术方向岗位的需要。
- 顶级 Stacking Context 置顶挂载:AI 配置弹窗 (Modal) 动态在
document.body根部挂载独立的 Shadow DOM 沙箱容器,彻底摆脱宿主页面各种嵌套容器层级(Stacking Context)的 z-index 压制与裁剪,在所有页面 100% 绝对置顶渲染。 - 特权跨域安全请求:利用油猴的
GM_xmlhttpRequest特权 API,100% 物理规避宿主招聘网站的 CSP (内容安全策略) 及同源策略 (CORS) 跨域网络限制,安全发送 API 请求。 - 双协议与动态模型适配:兼容 Gemini 官方接口协议与标准 OpenAI 接口协议,支持自定义 API KEY、Base URL、Model 及 System Prompt,可无缝对接国内的各种大模型(如 DeepSeek, Kimi 等)的反代服务。
- 零依赖高保真 Markdown 渲染:利用本地实现的轻量级正则 Markdown-to-HTML 编译转换引擎和
white-space: pre-wrap样式,完全不引入第三方包,保障脚本包体小巧,且 100% 避开宿主网站 AMD/CJS 加载器嗅探冲突。 - 就地持久化与秒开体验:诊断结论与职位记录一同在本地加密沙箱中进行持久化存储。下次查看同一岗位时秒级自动恢复展示,绝不重复消耗 API Token。
- 开发语言:TypeScript (Strict Mode,严格类型校验)
- 构建工具:Vite 5 +
vite-plugin-monkey(自动处理依赖并打包出带有 metadata 头的单文件.user.js) - UI 框架:原生 Web Components (Shadow DOM) + Vanilla CSS (高保真玻璃拟态暗黑风)
- 特权 APIs:
GM_setValue/GM_getValue(持久化沙箱)、GM_setClipboard(剪贴板注入)、GM_registerMenuCommand(油猴菜单注册)。
├── memory/ # 产品设计与系统设计文档
│ ├── architecture.md # 数据库设计、Schema 及反爬机制架构说明
│ └── prd.md # 产品需求规格与 SiteConfig 配置种子示例
├── src/
│ ├── config/ # 内置种子规则数据 ( seed.ts )
│ ├── engine/ # 核心配置驱动解析引擎与双源合并逻辑
│ ├── storage/ # GM 存储层封装、菜单指令与导入导出序列化
│ ├── ui/ # Shadow DOM 样式表、哈希随机类名防特征探测及面板组件
│ ├── utils/ # 系统运行辅助类 ( Logger 环形日志, ai.ts 评估请求引擎 )
│ ├── main.ts # 脚本主入口、原型防检测劫持层
│ └── scratch_test.ts # 包含 28 项断言测试的 Fake DOM 单元测试套件
├── .editorconfig # 编辑器代码风格统一配置
├── .gitattributes # Git 文件属性(统一换行符等)配置
├── .gitignore # Git 忽略文件规则配置
├── LICENSE # MIT 开源许可证
├── vite.config.ts # 打包元数据头配置
└── tsconfig.json # 严格 TS 校验规则
任何新平台的适配、更新或大改版,均表现为对以下 SiteConfig Schema 配置的修改或拉取更新,无需修改引擎代码:
export interface DetailParsers {
jobId: {
fromUrl?: string; // 从详情页 URL 提取 jobId 的正则
fromDom?: string[]; // 提取 jobId 的备选 DOM 选择器
};
title: string[]; // 职位名精准选择器 fallback 链
company: string[]; // 公司名选择器链
salary: {
selectors: string[]; // 薪资选择器链
regexFallback?: string; // 提取失败时,从正文匹配薪资的正则兜底
};
description?: string[]; // 职务描述 (JD) 选择器链
jobTags?: string[]; // 职位原始标签选择器链
}
export interface SiteConfig {
platformKey: string; // 平台简称 (如 'boss')
displayName: string; // 平台显示中文名
domains: string[]; // 匹配的域名子串 (如 ['zhipin.com'])
pages: {
detail?: {
urlPattern: string; // 判定为详情页的正则
injection: {
targetSelector: string[]; // 挂载随手记面板的锚点选择器优先级列表
position: 'append' | 'prepend' | 'before' | 'after' | 'fixed';
};
parsers: DetailParsers; // 详情页解析规则
};
list?: {
urlPattern: string; // 判定为列表页的正则
cardSelector: string; // 职位列表卡片的容器选择器
cardIdExtractor: {
attrName: string; // 存储 ID 的 DOM 属性名 (如 'data-jid')
regex?: string; // 从属性值中提取原始 ID 的正则
};
detailPreview?: {
triggerSelector: string; // 列表右侧预览分栏特征容器选择器
injection: {
targetSelector: string[];// 预览分栏内部随手记面板挂载锚点选择器
position: 'append' | 'prepend' | 'before' | 'after' | 'fixed';
};
parsers?: DetailParsers; // 预览专用的独立解析规则,若不提供则退避复用详情页规则
};
};
};
}npm install本项目编写了极其逼真的 Fake DOM 对象(支持后代选择器、逗号选择器、i 标志选择器匹配),可以在 Node 纯环境下脱离浏览器进行完整的核心引擎测试:
npx vite-node src/scratch_test.ts(全部 28 项测试均包含在此,确保重构或更新解析规则不会破坏现有平台的解析行为)。
npm run build打包产物位于 dist/job-nest.user.js。大小控制在约 109.70 KB。
- 打开 Chrome/Firefox 并安装浏览器插件 Tampermonkey。
- 运行
npm run build,打开生成的dist/job-nest.user.js并将其内容全部复制。 - 在 Tampermonkey 后台“新建脚本”,清空默认代码后粘贴复制的内容并保存。
- 打开 BOSS直聘列表页(如
/web/geek/job)或详情页:- 随手记面板会在挂载点就地浮现。
- 标注为“已看/拒绝”的岗位会在列表页中立即灰度弱化,标注“意向/已投递”或带有备注的岗位则自动浮现 Badge,悬停即可预览您的备忘录。
- 点击面板右下角版本号 5 下即可就地查阅运行日志,或从油猴菜单中快速导出数据和复制渲染源码。




