From 310f7abae18d47543344bc85a1c2141a4c962eae Mon Sep 17 00:00:00 2001 From: "zhiye.sun" Date: Fri, 14 Aug 2026 15:11:21 +0800 Subject: [PATCH] =?UTF-8?q?docs(project):=20=E5=AE=8C=E5=96=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E=E4=B8=8E=E5=AE=9E=E6=96=BD=E8=A7=84?= =?UTF-8?q?=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 50 ++++++++++++ README.md | 183 +++++++++++++++++++++++++++++++++++++++++++ docs/architecture.md | 116 +++++++++++++++++++++++++++ docs/roadmap.md | 95 ++++++++++++++++++++++ environment.yml | 12 +++ 5 files changed, 456 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docs/architecture.md create mode 100644 docs/roadmap.md create mode 100644 environment.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..58edfdd --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +# Python 字节码与缓存 +__pycache__/ +*.py[cod] +*$py.class + +# Python 构建与包文件 +build/ +dist/ +*.egg-info/ +.eggs/ + +# 虚拟环境 +.venv/ +venv/ +env/ + +# Django 本地运行数据 +db.sqlite3 +db.sqlite3-journal +media/ +staticfiles/ + +# 测试、覆盖率和类型检查缓存 +.pytest_cache/ +.coverage +htmlcov/ +.mypy_cache/ +.ruff_cache/ + +# 本地配置、密钥与日志 +.env +.env.* +!.env.example +*.log +logs/ + +# IDE 与编辑器 +.idea/ +.vscode/ +*.swp +*.swo + +# 操作系统文件 +.DS_Store +Thumbs.db +Desktop.ini + +# Playwright 本地产物 +playwright-report/ +test-results/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..7127433 --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +# JobRadar · 职途雷达 + +JobRadar 是一套面向个人使用的智能岗位发现与决策系统。项目计划从指定招聘网站采集岗位信息,依据可配置规则完成筛选,并结合联网检索与大模型分析补充企业性质、岗位匹配度、判断依据和置信度,最终形成可追溯的个人岗位库。 + +> 当前项目处于基础骨架阶段,已完成 Django 工程初始化;岗位采集、企业研判、评分、异步任务和业务页面均在后续迭代范围内。 + +## 项目目标 + +- 通过独立站点适配器采集授权范围内的岗位信息。 +- 统一不同来源的岗位字段,并识别重复岗位和内容变化。 +- 使用硬性规则优先排除明显不符合要求的岗位。 +- 联网补充企业主体、企业性质和行业等信息,保留来源与查询时间。 +- 按可配置权重计算岗位匹配分,输出推荐理由和风险提示。 +- 提供适合个人使用的岗位管理、收藏、忽略和投递跟踪页面。 +- 保留原始数据、规则版本和分析证据,使每项结论可以复核。 + +## 技术栈 + +| 分类 | 选型 | 当前状态 | +| --- | --- | --- | +| 开发语言 | Python 3.13 | 已配置 | +| Web 框架 | Django 6.0.8 | 已配置 | +| 当前数据库 | SQLite | 已配置,仅用于开发起步 | +| 目标数据库 | PostgreSQL | 规划中 | +| 页面采集 | Playwright | 环境已安装,尚未接入 | +| 普通请求 | HTTPX | 规划中 | +| 异步任务 | Celery + Redis | 规划中 | +| 定时调度 | Celery Beat | 规划中 | +| AI 分析 | 兼容 OpenAI 接口的模型服务 | 规划中 | +| 用户系统 | Django 内置认证 + 简化用户资料 | 规划中 | +| WebUI | Django Admin + 自定义 Django 页面 | 规划中 | +| 部署 | Docker Compose + Nginx/Caddy + HTTPS | 规划中 | + +第一阶段优先采用 Django Admin 管理站点、规则、企业和任务数据,再为岗位浏览与决策流程开发自定义页面。出现明确的前后端分离需求后,再评估是否增加 Django REST Framework 和 Vue。 + +## 当前目录 + +```text +JobRadar/ +├── JobRadar/ Django 项目配置 +│ ├── asgi.py +│ ├── settings.py +│ ├── urls.py +│ └── wsgi.py +├── docs/ 架构与实施文档 +├── templates/ 全局 Django 模板 +├── environment.yml Conda 环境定义 +├── manage.py Django 管理入口 +└── README.md +``` + +业务模块将随迭代逐步增加,暂定拆分为: + +```text +accounts/ 用户认证、个人配置与数据归属 +jobs/ 岗位、岗位来源及状态跟踪 +companies/ 企业主体及企业证据 +crawlers/ 招聘网站采集适配器 +screening/ 硬性筛选规则 +ranking/ 权重评分 +ai_analysis/ 语义分析及结构化输出 +task_center/ 采集、分析与调度任务 +audit/ 日志、证据与版本追踪 +``` + +详细边界参见 [架构设计](docs/architecture.md),开发顺序参见 [实施路线图](docs/roadmap.md)。 + +## 本地运行 + +### 1. 创建或更新 Conda 环境 + +如果本机还没有 `JobRadar` 环境: + +```powershell +conda env create -f environment.yml +``` + +如果环境已经存在: + +```powershell +conda env update -n JobRadar -f environment.yml --prune +``` + +激活环境: + +```powershell +conda activate JobRadar +``` + +### 2. 检查数据库迁移 + +当前默认使用项目目录中的 SQLite 数据库: + +```powershell +python manage.py migrate +``` + +### 3. 创建本地管理员 + +```powershell +python manage.py createsuperuser +``` + +### 4. 启动开发服务 + +```powershell +python manage.py runserver +``` + +访问地址: + +- 管理后台: + +### 5. 安装 Playwright 浏览器 + +首次开发采集模块时执行: + +```powershell +python -m playwright install chromium +``` + +浏览器文件不应提交到仓库。 + +## 配置原则 + +- 本地开发密钥、数据库密码、招聘网站 Cookie 和模型 API Key 不得提交到 Git。 +- 当前 `settings.py` 仍是 Django 生成的开发配置,不可直接用于生产环境。 +- 接入 PostgreSQL 前,应先增加本地配置文件或环境隔离方案,并提供不含真实密钥的示例配置。 +- 采集器必须设置并发、频率、超时和指数退避,不能绕过验证码、登录保护或访问控制。 +- 企业性质及 AI 判断必须保存来源、判断时间和置信度;信息不足时应标记为待人工复核。 + +## 用户系统 + +系统面向公网部署,因此第一阶段即接入用户认证,但不设计复杂的角色权限体系: + +- 使用 Django 内置用户、密码哈希、Session 和登录保护能力。 +- 普通用户登录后只能访问自己的搜索任务、筛选配置、岗位状态和个人画像。 +- 管理员使用 Django Admin 维护站点适配器、系统任务和异常数据。 +- 第一阶段只区分普通用户与管理员,不增加角色表、权限组、组织机构或审批流。 +- 业务数据必须记录所属用户,查询和任务执行时统一校验数据归属。 +- 默认关闭公开注册,由管理员创建账号;确需开放注册时再增加邮箱验证、验证码和频率限制。 + +## 公网部署要求 + +- Django 由生产级 WSGI/ASGI 服务运行,不能使用 `manage.py runserver` 对外提供服务。 +- 使用 Nginx 或 Caddy 作为反向代理,并强制启用 HTTPS。 +- 正确配置 `ALLOWED_HOSTS`、可信 CSRF 来源、安全 Cookie 和代理转发头。 +- PostgreSQL 和 Redis 仅在容器私有网络中开放,不映射到公网。 +- 登录、注册、密码重置和耗时接口应设置频率限制与异常审计。 +- 密钥、数据库密码、网站 Cookie 和模型 API Key通过部署平台密钥或受保护的环境配置注入。 +- 定期备份数据库,并验证备份恢复流程。 + +## 开发约定 + +- 一个招聘网站对应一个采集适配器,禁止把站点特有解析逻辑写入公共业务模块。 +- 原始数据与标准化数据分开保存,避免解析规则变化后无法追溯。 +- 先执行确定性筛选,再调用联网服务和大模型,降低成本与误判范围。 +- 评分权重由配置决定,大模型只输出结构化维度分析,不直接修改最终分数。 +- 采集、企业补全和 AI 分析任务必须可重复执行,并通过唯一约束或幂等键防止重复入库。 +- 重要判断应包含证据,不以模型生成的自然语言作为唯一依据。 + +## 验证命令 + +```powershell +python manage.py check +python manage.py test +``` + +涉及数据模型变更时,还应检查是否遗漏迁移文件: + +```powershell +python manage.py makemigrations --check --dry-run +``` + +## 合规说明 + +JobRadar 仅用于个人岗位信息整理与求职辅助。使用前应确认目标网站的服务条款、数据授权范围和访问频率限制。项目不以绕过验证码、风控、登录限制或其他技术保护措施为目标,也不应自动投递简历或自动联系招聘人员。 + +## 项目状态 + +当前版本:`0.1.0-dev` + +当前阶段:Django 基础工程和项目文档初始化。 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..cd093b4 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,116 @@ +# JobRadar 架构设计 + +## 设计原则 + +JobRadar 第一阶段采用模块化单体架构。Django 负责业务模型、管理后台、自定义页面和任务入口;耗时的浏览器采集、企业信息补全和 AI 分析由异步 Worker 执行。各业务模块在代码层隔离,但共享 PostgreSQL 数据库,避免在个人项目初期引入微服务通信和部署成本。 + +## 目标架构 + +```mermaid +flowchart LR + USER["公网用户"] --> PROXY["Nginx / Caddy 与 HTTPS"] + PROXY --> WEB["Django 登录、Admin 与岗位工作台"] + WEB --> APP["Django 业务应用"] + APP --> DB[("PostgreSQL")] + APP --> REDIS["Redis"] + BEAT["Celery Beat"] --> REDIS + REDIS --> WORKER["Celery Worker"] + WORKER --> COLLECT["Playwright / HTTPX 采集"] + WORKER --> ENRICH["企业信息联网补全"] + WORKER --> AI["LLM 结构化分析"] + COLLECT --> DB + ENRICH --> DB + AI --> DB +``` + +## 用户与权限边界 + +系统支持公网访问,第一阶段采用简化的用户体系: + +- 直接使用 Django 内置用户、认证、Session 和密码管理能力。 +- 普通用户拥有个人画像、搜索任务、筛选规则、评分配置和岗位操作记录。 +- 所有用户私有业务表通过所属用户字段隔离,服务层和查询层统一限制当前用户的数据范围。 +- 管理员通过 Django Admin 维护全局站点配置、采集状态和异常数据。 +- 第一阶段仅区分普通用户与管理员,不建设 RBAC、组织机构、岗位角色和审批授权模型。 +- 默认由管理员创建账号并关闭公开注册;开放注册属于后续独立功能。 + +即使初期实际只有一个账号,数据模型仍保留用户归属,避免未来增加账号时重新改造所有核心表。 + +## 处理链路 + +1. 用户配置目标网站、关键词、地区、硬性条件和评分权重。 +2. 调度器创建采集批次,站点适配器获取并保存原始岗位记录。 +3. 标准化模块统一岗位、公司、薪资、经验和地点字段。 +4. 去重模块根据来源岗位编号、内容指纹和标准化字段建立岗位关系。 +5. 筛选模块先执行可确定判断的硬规则,并记录通过、淘汰或待确认原因。 +6. 企业补全模块查询可信来源,保存企业主体、性质、证据和置信度。 +7. AI 模块对通过初筛的岗位进行技能、职责、风险和匹配度分析。 +8. 评分模块根据固定公式生成最终分数,并保存评分配置版本。 +9. 用户在岗位工作台中收藏、忽略或更新投递状态。 + +## 模块边界 + +### 采集模块 + +- 优先使用网站允许访问的接口或普通 HTTP 请求,动态页面才使用 Playwright。 +- 每个网站独立实现适配器,并输出统一的原始岗位数据对象。 +- 负责限流、超时、重试和采集状态,不负责岗位评分。 +- 页面变更导致解析失败时,应保留错误证据并暂停对应适配器。 + +### 标准化与去重模块 + +- 原始数据只追加或生成新版本,不被标准化结果覆盖。 +- 同站唯一键建议为“站点编号 + 来源岗位编号”。 +- 跨站重复判断结合公司标准名、岗位名、地点、薪资和内容指纹。 +- 跨站重复岗位建立关联,不直接物理删除来源记录。 + +### 企业补全模块 + +- 按企业标准名称或统一社会信用代码识别主体。 +- 结论至少保存来源地址、证据摘要、获取时间和置信度。 +- 多来源冲突、主体不明确或置信度不足时进入人工复核。 +- 人工确认结果优先级高于自动判断,但不得删除历史证据。 + +### AI 分析模块 + +- 输入为标准化岗位、个人画像和必要证据,不直接使用未经清洗的整页内容。 +- 输出必须通过结构化模型校验,不接受无法解析的自由文本作为业务结果。 +- 记录模型名称、提示词版本、输入摘要和分析时间。 +- 相同内容与同一分析版本应优先复用缓存结果。 + +### 评分模块 + +- 硬性条件和最终加权公式由确定性代码执行。 +- 每个评分维度保留原始分、权重、加权分和判断依据。 +- 权重或规则变化时创建新版本,历史结果仍可回溯。 +- 风险扣分与正向评分分开保存,避免结果无法解释。 + +## 数据边界 + +第一阶段核心实体包括: + +- 招聘网站及站点配置 +- 搜索任务与采集批次 +- 原始岗位记录与标准化岗位 +- 企业主体与企业证据 +- 筛选规则、规则版本和筛选结果 +- 评分配置、评分结果和 AI 分析记录 +- 收藏、忽略、投递和面试状态 +- 任务日志与人工复核记录 + +具体字段应在首个目标网站和筛选规则明确后再落地,避免提前设计大量无法验证的字段。 + +## 部署边界 + +系统目标部署到公网。目标运行单元为: + +```text +web Django Web 服务 +worker Celery Worker +beat Celery 定时调度 +postgres PostgreSQL +redis Redis +proxy Nginx 或 Caddy 反向代理及 HTTPS 终止 +``` + +公网只开放反向代理的 HTTP/HTTPS 端口。Django、PostgreSQL 和 Redis 位于容器私有网络;Django 使用生产级 WSGI/ASGI 服务运行,不使用开发服务器对外提供服务。部署时必须配置 HTTPS、安全 Cookie、`ALLOWED_HOSTS`、可信 CSRF 来源、登录限流、密钥注入、日志审计和数据库备份。 diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..e7fa1d3 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,95 @@ +# JobRadar 实施路线图 + +## 阶段一:基础工程 + +目标是建立可持续开发的 Django 项目基线。 + +- [x] 初始化 Django 项目。 +- [x] 创建 Conda 环境。 +- [x] 创建本地和远程 Git 仓库。 +- [x] 补充项目、架构和路线图文档。 +- [ ] 拆分开发、测试和生产配置。 +- [ ] 将密钥及本地配置移出版本库。 +- [ ] 接入 Django 用户认证并建立用户资料模型。 +- [ ] 为搜索任务、筛选配置和岗位操作增加用户归属。 +- [ ] 默认关闭公开注册,只保留管理员创建账号入口。 +- [ ] 接入 PostgreSQL 并建立迁移基线。 +- [ ] 增加统一日志、测试和代码质量工具。 + +## 阶段二:单站采集闭环 + +目标是稳定采集一个明确授权范围内的招聘网站。 + +- [ ] 确认首个目标网站及其服务条款和访问边界。 +- [ ] 定义站点适配器协议和原始岗位数据结构。 +- [ ] 实现搜索任务、采集批次和原始岗位模型。 +- [ ] 实现首个站点适配器。 +- [ ] 增加限流、超时、重试和失败日志。 +- [ ] 完成来源岗位编号去重和内容变更识别。 +- [ ] 在 Django Admin 中提供任务和原始数据管理能力。 + +验收条件:可以手动运行一次采集,查看新增、更新、重复和失败数量,并从标准化岗位追溯到原始来源。 + +## 阶段三:岗位标准化与筛选 + +目标是用确定性规则减少无效岗位。 + +- [ ] 定义岗位、企业和岗位来源模型。 +- [ ] 标准化岗位名、地点、薪资、经验和学历。 +- [ ] 建立排除词、黑名单和硬性筛选规则。 +- [ ] 输出通过、淘汰和待确认结果及具体原因。 +- [ ] 实现岗位列表、详情、收藏、忽略和投递状态。 +- [ ] 保存规则版本,支持重新筛选历史岗位。 + +验收条件:不调用大模型也能稳定过滤明确不符合要求的岗位,并解释每条淘汰原因。 + +## 阶段四:企业联网补全 + +目标是可靠判断企业主体和企业性质。 + +- [ ] 确定合法、稳定的企业信息来源。 +- [ ] 建立企业别名、标准主体和证据模型。 +- [ ] 保存企业性质、行业、集团、来源和置信度。 +- [ ] 实现多来源冲突检测和待复核队列。 +- [ ] 支持人工确认,并保留自动判断历史。 + +验收条件:企业性质结论包含可访问的来源和查询时间,无法确认的企业不会被强行分类。 + +## 阶段五:AI 分析与权重评分 + +目标是形成可解释的岗位推荐结果。 + +- [ ] 定义个人岗位画像和技能偏好。 +- [ ] 定义结构化 AI 输出模型。 +- [ ] 提取技能、职责、隐含条件和风险点。 +- [ ] 实现可配置评分维度及权重校验。 +- [ ] 保存维度分数、风险扣分、理由和分析版本。 +- [ ] 对相同内容建立缓存,控制调用成本。 + +验收条件:每个总分都可以分解到评分维度、权重和证据,大模型不能越过硬性规则直接改变结果。 + +## 阶段六:调度、通知与扩站 + +目标是让系统长期稳定运行。 + +- [ ] 接入 Celery、Redis 和 Celery Beat。 +- [ ] 实现任务幂等、指数退避和失败恢复。 +- [ ] 增加任务中心与运行状态展示。 +- [ ] 增加高分新岗位通知。 +- [ ] 增加第二个站点适配器,验证扩展边界。 +- [ ] 增加备份、清理和恢复机制。 +- [ ] 使用 Nginx 或 Caddy、生产级应用服务器和 HTTPS 完成公网部署。 +- [ ] 增加安全 Cookie、CSRF、登录限流和安全响应头检查。 + +验收条件:定时任务连续运行时不会重复创建岗位,单个站点失败不会影响其他任务,异常可以从日志和任务记录中定位。 + +## 第一轮开发前待确认 + +1. 首个目标招聘网站及允许使用的访问方式。 +2. 搜索岗位、城市、薪资、经验和学历范围。 +3. 必须包含与必须排除的关键词。 +4. 企业性质、行业和公司规模偏好。 +5. 评分维度及初始权重。 +6. 企业信息数据源和大模型服务方式。 +7. 运行频率、单次采集页数和通知渠道。 +8. 公网域名、部署服务器和 HTTPS 证书管理方式。 diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000..546c852 --- /dev/null +++ b/environment.yml @@ -0,0 +1,12 @@ +name: JobRadar +channels: + - defaults +dependencies: + - python=3.13 + - django=6.0.8 + - pip + - pip: + # 页面采集和 PostgreSQL 驱动已存在于当前开发环境,先纳入可复现环境定义。 + - playwright==1.60.0 + - psycopg2-binary==2.9.12 + - pillow==12.2.0