292 lines
18 KiB
Markdown
292 lines
18 KiB
Markdown
# 招聘考试信息聚合系统 · 总计划书(设计稿 v0.1)
|
||
|
||
> 状态:**设计/规划阶段,暂不开发**。本文档用于锁定范围、对齐架构、暴露风险,并列出需你拍板的关键决策。
|
||
> 落点:作为 **service.xpcool.com(Go 后端模块)** + **admin.xpcool.com(Vue 管理/可视化前端模块)** 的一个功能模块。
|
||
> 默认地区:**贵阳市**;架构需天然支持全省 9 个市州 + 省直,便于后续扩展。
|
||
|
||
---
|
||
|
||
## 0. 文档约定
|
||
|
||
- 术语:**发布主体**(谁发的,可能是机关/事业单位/国企/央企/私企)、**考试分类**(公务员/事业单位/国企/央企/私企/其他)、**公告**(一条招聘考试信息)。两者解耦,才能支撑你想要的"按企业 + 按分类"双重筛选。
|
||
- 时间基线:2026-08-27。历史全量定义为"近 2 年"(2024-08 起)。
|
||
- 所有域名/接口形态均来自 2026-08 真实联网核查,标注【已核验】;其余为规划假设,需 POC 验证。
|
||
|
||
---
|
||
|
||
## 1. 业务目标与成功标准
|
||
|
||
**你要做的事(复述对齐):**
|
||
1. 爬取贵州各地区**官方渠道**发布的招聘考试信息。
|
||
2. 默认聚焦贵阳,支持多分类筛选:公务员、事业单位、国企、央企、私企等。
|
||
3. 先做一次**近两年全量历史**回溯,再**每天增量**抓取最新。
|
||
4. 每天早上诉**Bark** 推送给你。
|
||
5. 在 admin 里做**可视化展示 + 数据分析**。
|
||
|
||
**成功标准(建议,可调整):**
|
||
- 贵阳 + 公务员/事业单位/国企/央企 四类,官方源覆盖率 ≥ 90%,公告从发布到入库延迟 < 24h。
|
||
- 每日早上推送稳定到达(失败有兜底告警)。
|
||
- 去重准确率 ≥ 99%(同一公告多站转发不重复计)。
|
||
- admin 可对任意"地区 × 分类 × 时间"组合做筛选与趋势分析。
|
||
|
||
---
|
||
|
||
## 2. 数据源调研(贵州真实官方渠道)【已核验 2026-08】
|
||
|
||
### 2.1 省级统一门户
|
||
| 名称 | 域名 | 形态 | 覆盖分类 | 备注 |
|
||
|---|---|---|---|---|
|
||
| 贵州人事考试信息网 | `gzrsks.com.cn`【已核验】 | **SPA(hash 路由)** | 公务员招录、事业单位招聘、资格考试、"三支一扶" | 全省最核心门户,但**是前端渲染,需找底层 JSON 接口或用 headless 渲染** |
|
||
| 贵州省公务员局 | `gzzzb.gov.cn`【已核验】 | 静态列表页 | 公务员(省/市/县/乡四级联考、遴选) | 公告 + 职位表,链接常回链到 gzrsks 专题页 |
|
||
| 贵州人力资源社会保障网 | `rst.guizhou.gov.cn` | 静态 | 省直事业单位、人才引进 | 省本级发布渠道 |
|
||
|
||
### 2.2 贵阳市(默认地区,已核验可抓)
|
||
| 名称 | 域名 | 栏目/路径 | 覆盖 |
|
||
|---|---|---|---|
|
||
| 贵阳市人力资源和社会保障局 | `rsj.guiyang.gov.cn`【已核验】 | `rszk` 人事招考 | 事业单位、教师、卫健、"三支一扶"、局属单位 |
|
||
| 贵阳市人民政府 | `guiyang.gov.cn`【已核验】 | 人事招考 / 招聘信息 | 转发市直单位招聘公告 |
|
||
|
||
### 2.3 其他地区(9 市州 + 省直,需 POC 验证)
|
||
架构预留,首批不做。后续按"市州人社局官网 + 市政府门户人事招考栏目"模式复制:
|
||
**遵义、六盘水、安顺、毕节、铜仁、黔东南州、黔南州、黔西南州** + **省直**(已在 2.1 覆盖)。
|
||
> 注意:部分市州门户为静态、部分也是 SPA,难度不一,需逐个 POC。
|
||
|
||
### 2.4 国企 / 央企【已核验】
|
||
| 渠道 | 域名 / 地址 | 备注 |
|
||
|---|---|---|
|
||
| 贵州省国资委国资央企招聘平台 | `cujiuye.iguopin.com`【已核验】 | 243 家国企夏季招聘(茅台、旅投、磷化、乌江能源、盐业、路桥…),规模大 |
|
||
| 中国贵州茅台集团 | `moutaichina.com` / `moutai.com.cn`【已核验】 | 高层次人才/应届引才,附件多(xlsx/docx) |
|
||
| 贵州电网 | 南网招聘系统 `zhaopin.csg.cn`【已核验】 | 公告常经 gov 站/聚合站转发,源头在系统内需登录 |
|
||
| 其他省属/在黔央企 | 各集团官网"人才招聘"栏目 | 名单见国资委平台,逐一登记 |
|
||
|
||
### 2.5 私企 / 其他 —— **明显的覆盖缺口,需你决策**
|
||
- 纯私企几乎**不在政府官网**发"招聘考试"。其信息散落在:① 企业自己官网"招聘/校园招聘"栏目;② 招聘聚合站(智联、BOSS、猎聘、高校人才网等);③ 微信公众号。
|
||
- 建议分期:首批**只做官方/半官方源**(公务员/事业/国企/央企),"私企"作为**二期**,来源改为"知名民营企业官网招聘页 + 1~2 个可信聚合站",并明确标注来源为非官方。
|
||
- 风险:聚合站有版权与反爬限制,且信息噪声大,需更强的清洗与去重。
|
||
|
||
### 2.6 数据源分级(决定技术难度)
|
||
- **A 类 静态列表页**:goquery 直接解析(如 rsj.guiyang.gov.cn)。最易。
|
||
- **B 类 SPA / JS 渲染**:需定位底层 API 或 headless 渲染(如 gzrsks.com.cn)。**最难,是工期主要风险点。**
|
||
- **C 类 需登录/验证码**:如南网招聘系统、部分企业内网。首批排除,人工或后续对接。
|
||
- **D 类 附件型**:公告正文在 PDF/Word(如茅台 xlsx 岗位表)。需附件解析抽取关键字段。
|
||
|
||
---
|
||
|
||
## 3. 整体技术架构
|
||
|
||
### 3.1 部署拓扑(复用现有底座)
|
||
- 复用腾讯云 `193.112.118.168`(CentOS Stream,SSH 22025,账号 xxcool)。
|
||
- 复用 Docker + `xpcool-net` 网络 + 宿主机 Nginx。
|
||
- **后端模块**挂进现有 `service.xpcool.com:new` 容器(已有 `127.0.0.1:10100:10100`、env `GF_GCFG_ENV=prod` + `DB_DSN`(须带 `mysql:` 前缀) + `JWT_SECRET`,且容器内必须有 `manifest/config/config.yaml`)。
|
||
- **前端模块**挂进 `admin.xpcool.com`,Nginx 落点 `/data/www/admin.xpcool.com/`。
|
||
- **Bark**:建议与现有服务同机或独立容器部署(见 §6)。
|
||
|
||
### 3.2 模块划分
|
||
```
|
||
[数据源网站]
|
||
│ (HTTP / API / headless)
|
||
▼
|
||
[Crawler 爬虫引擎] ── 调度器(cron, 每日凌晨) ──┐
|
||
│ 去重/字段抽取/附件解析 │
|
||
▼ │
|
||
[MySQL 存储] ◀── 读写 ── [service 后端 API 模块 /recruitment/*]
|
||
│ │
|
||
│ [admin 前端模块]
|
||
│ │
|
||
[Bark 推送器] ◀── 每日早报任务 ────────────────┘
|
||
```
|
||
|
||
### 3.3 技术选型(对齐现有底座)
|
||
- 后端:**Go + com.lib.gf.v2 + com.lib.v2**(与 service 同源,复用 ORM/配置/日志/JWT)。新增 `recruitment` 模块包。
|
||
- 前端:**Vue + TDesign**(admin 现有约定,写组件前先走 TDesign MCP 查官方文档)。
|
||
- 存储:**MySQL**(复用 service 库,或独立 `recruitment` 库——见决策点)。
|
||
- 调度:Go 内置 cron(如 gocron)常驻于 service 进程;或系统 crontab 调内部 API(二选一)。
|
||
- 动态渲染:**Playwright**(Python/Node sidecar 或 CLI),仅 B 类 SPA 按需调用,避免全量上浏览器。
|
||
|
||
---
|
||
|
||
## 4. 数据模型设计(草案)
|
||
|
||
> 发布主体与考试分类解耦,支撑"按企业 + 按分类"双重筛选。
|
||
|
||
**recruitment_info(公告主表)**
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | bigint PK | |
|
||
| title | varchar | 标题 |
|
||
| source_id | bigint FK | 数据源(crawl_source) |
|
||
| org_id | bigint FK | 发布主体(organization) |
|
||
| category | tinyint | 考试分类(1公务员/2事业单位/3国企/4央企/5私企/6其他) |
|
||
| region | varchar | 地区(贵阳/省直/遵义…),支持多级 |
|
||
| publish_date | date | 发布日期 |
|
||
| deadline | date NULL | 报名/截止日期(抽取) |
|
||
| exam_date | date NULL | 笔试日期(抽取) |
|
||
| url | varchar | 原文链接(唯一性依据之一) |
|
||
| content | longtext | 正文/摘要 |
|
||
| attachments | json NULL | 附件链接与解析结果 |
|
||
| status | tinyint | 0有效/1已更正/2已失效/3已删除 |
|
||
| fingerprint | varchar | 去重指纹 |
|
||
| created_at / updated_at | datetime | |
|
||
|
||
**organization(发布主体)**:id, name, type(机关/事业/国企/央企/私企/其他), official_site, region。
|
||
**crawl_source(数据源配置)**:id, name, base_url, type(A/B/C/D), list_selector/api_path, cron_expr, enabled, last_success_at, fail_count。
|
||
**crawl_log(抓取日志)**:id, source_id, run_at, fetched, new, updated, error。
|
||
**push_subscription(推送订阅)**:id, device_key(Bark), regions(json), categories(json), only_new(bool), push_time。
|
||
**push_log(推送记录)**:id, subscription_id, push_at, title, body, result。
|
||
|
||
索引:url(唯一)、fingerprint(唯一)、(region, category, publish_date) 复合索引支撑筛选与趋势。
|
||
|
||
---
|
||
|
||
## 5. 爬虫设计
|
||
|
||
### 5.1 抓取策略
|
||
- **全量历史(首跑)**:对每个 A/B/C 类源,按列表分页从当前回溯到 2024-08;D 类附件一并下载解析。
|
||
- **增量(每日)**:每日凌晨对全部 enabled 源巡检列表前 N 页(覆盖当天新发),入库新公告 / 更新已存在公告的 status(官网更正/取消时标记而非硬删)。
|
||
|
||
### 5.2 解析方式(按源分级)
|
||
- A 类:goquery CSS 选择器解析列表 + 详情。
|
||
- B 类 SPA:先抓 XHR/JSON(浏览器 DevTools 看接口);拿不到再走 Playwright 渲染后抽取。
|
||
- D 类:下载 PDF/Word → 文本抽取 → 正则提"报名/笔试/截止"日期与岗位数。
|
||
|
||
### 5.3 去重与更新
|
||
- 指纹 = `hash(source_id + normalize(title) + publish_date + url)`;同公告多站转发视为多条**不同来源记录**但关联同一 `group_key`(如 `hash(title+publish_date)`),前端可按 group 聚合展示"多家来源"。
|
||
- 更新检测:再次抓取时比对 content 哈希,变化则更新 + 记 crawl_log。
|
||
|
||
### 5.4 反爬与稳定性
|
||
- 统一限速(每源间隔 ≥ 2~5s)、随机 UA、超时重试(指数退避)、失败计数。
|
||
- 连续失败 ≥ 阈值:标记源异常 + **Bark/邮件告警**(避免静默失效)。
|
||
- 代理池(可选,IP 被封时启用)。
|
||
|
||
### 5.5 字段抽取难点
|
||
- 截止/笔试日期、招聘人数、学历要求:正文正则 + 模板兜底;首批对样本做人工校验,调置信度。
|
||
- 地区推断:优先取源所属地区,正文含"贵阳/遵义…"可校正。
|
||
|
||
### 5.6 调度
|
||
- 每日 02:00–05:00 增量巡检(错峰、规避官网高峰)。
|
||
- 首跑全量可手动触发 + 分批(按源、按月份)防止单次过长。
|
||
|
||
---
|
||
|
||
## 6. Bark 每日推送设计
|
||
|
||
### 6.1 自建 vs 公共(决策点)
|
||
- **公共 `api.day.app`**:零部署,POST `https://api.day.app/push` `{device_key,title,body,group,url}` 即可。代价:通知文本经第三方。**推荐先走公共版跑通,再决定是否自建。**
|
||
- **自建 `finab/bark-server`(Docker)**:隐私可控,但**必须配置 APNs 证书(p8+KeyID+TeamID)才能真正推到 iPhone**,且需域名+HTTPS。运维成本更高。
|
||
- 你的腾讯云同机部署可行(另开端口或子域名 + Caddy 自动证书)。
|
||
|
||
### 6.2 每日早报模板(建议)
|
||
```
|
||
【贵州招聘早报 · 2026-08-27 · 贵阳】
|
||
昨日新增:公务员 0 · 事业单位 3 · 国企 1 · 央企 0 · 私企 0
|
||
🔥 重点关注:
|
||
· 贵阳贵安2026事业单位面试公告(截止 08-30)
|
||
· 贵州电网春招补录(截止 09-05)
|
||
👉 点击查看详情:https://admin.xpcool.com/recruitment
|
||
```
|
||
- 用 `group=recruit_daily` 分组;`level=active`;`url` 深链到 admin 对应筛选页。
|
||
|
||
### 6.3 订阅过滤
|
||
- 按 `push_subscription`:可配置"仅贵阳""仅公务员+事业单位""仅推送新公告"。
|
||
- 多设备/多人可扩展(家人/同事各一 key)。
|
||
|
||
### 6.4 时机与兜底
|
||
- 默认 **每天早上 08:00** 推送(可配置)。
|
||
- 推送失败:记录 push_log + 重试 1 次 + 仍失败则 Bark 告警自身(用另一个 key/渠道)。
|
||
|
||
---
|
||
|
||
## 7. 可视化与数据分析(admin 模块)
|
||
|
||
- **仪表盘**:总公告数、近 30 天新增、按分类占比环图、按地区柱状、今日/昨日新增卡片。
|
||
- **列表 + 筛选**:地区(多级)、分类(多选)、发布时间范围、关键词(标题/正文/单位全文检索)、状态(有效/已失效);表格 + 详情抽屉(原文链接、附件、多来源聚合)。
|
||
- **趋势分析**:按月/按地区/按分类的时间序列折线;支持导出 Excel/CSV。
|
||
- **爬虫运维面板**:各源最后成功时间、失败次数、今日抓取量、手动触发按钮、日志查看。
|
||
- **权限**:复用 admin 现有 JWT + `admin_menu`(type=2) 路由注册(path 须与实际前端路由匹配,历史踩坑点)。
|
||
|
||
---
|
||
|
||
## 8. 你没想到 / 容易踩的坑(重点补充)
|
||
|
||
**法律与合规**
|
||
1. **robots.txt 与版权**:政府官网通常允许转载但需注明来源;逐站评估使用条款,正文展示标注"来源:XXX"并链回原文。
|
||
2. **个人隐私边界**:只聚合"公告本身",**绝不抓取报名系统表单/考生个人信息**。
|
||
3. **数据使用边界**:仅作个人/内部信息聚合展示,不篡改、不商业化转售。
|
||
|
||
**反爬与可用性(最大的技术风险)**
|
||
4. **SPA 抓不到正文**:gzrsks.com.cn 是 hash 路由 SPA,纯 HTTP 拿不到内容——必须先做接口逆向或上 Playwright,**这是首跑 POC 的第一关**。
|
||
5. **IP 被封 / 频率限制**:需限速、随机 UA、代理池、退避重试。
|
||
6. **网站改版**:模板一变解析器即失效,需"解析失败即告警"而非静默。
|
||
7. **登录/验证码源**:南网招聘系统等首批排除,避免卡住整体进度。
|
||
|
||
**数据质量**
|
||
8. **去重准确性**:同公告多站转发 ≠ 重复;用 group_key 聚合、用 fingerprint 防真重复。
|
||
9. **公告变更/撤回**:官网更正或取消招聘,应标记 `status`(已更正/已失效),**不要硬删**,否则趋势断裂。
|
||
10. **日期/人数抽取易错**:正文格式多样,首批必须人工抽检样本校准正则。
|
||
11. **附件解析**:PDF/Word 岗位表里的关键信息(特别是茅台类)需单独抽取管线。
|
||
|
||
**覆盖与完整性**
|
||
12. **历史全量能否拿到**:部分官网旧公告会被归档或删除,近两年回溯可能不完整;POC 阶段就要验证"能回溯到多久"。
|
||
13. **增量漏抓补偿**:某天爬虫失败,次日需补抓(而非只抓"今天"),设计成"按发布日期窗口回扫"。
|
||
14. **新源发现机制**:新出现的发布渠道如何纳入——建"候选源登记 + 人工审核"流程,而非自动信任。
|
||
15. **私企覆盖缺口**:无官方源,需明确二期方案与来源可信度标注(见 §2.5)。
|
||
|
||
**运维与告警**
|
||
16. **爬虫失败必须告警**:某源连续失败 N 次 → Bark/邮件通知,否则你以为在跑其实已挂。
|
||
17. **推送本身要可观测**:push_log + 失败重试 + 独立告警通道。
|
||
|
||
**产品与体验**
|
||
18. **搜索是刚需**:标题/正文/单位全文检索,否则数据多了找不到。
|
||
19. **收藏/关注**:可标记"关注的单位/分类",推送可只推关注的。
|
||
20. **数据导出**:Excel/CSV 供你自己分析。
|
||
21. **移动端查看**:admin 是否要移动适配(你主要手机看推送,但详情可能在 admin)。
|
||
|
||
**集成与部署**
|
||
22. **与现有 service/admin 权限体系对接**:复用 JWT、`admin_menu` 路由(type=2 path 匹配历史坑)、`xpcool-net` 网络、env(DB_DSN 带 `mysql:` 前缀、JWT_SECRET)。
|
||
23. **爬虫常驻 vs 独立容器**:放进 service 进程省运维面,但 SPA 渲染要 Playwright sidecar——资源与隔离如何权衡(见决策点)。
|
||
24. **配置外置**:爬虫源、Bark key、推送时间、地区默认走配置/环境变量,不写死代码。
|
||
|
||
**技术决策点(待你拍板)**
|
||
25. 爬虫语言/形态:**纯 Go 适配器** vs **Python 爬虫微服务**写同一库?Go 同源易部署但 SPA/Playwright 生态弱;Python 爬虫生态成熟但多一个服务。
|
||
26. 存储:**复用 service 库** vs **独立 recruitment 库**?独立库隔离风险、便于单独备份与扩容。
|
||
|
||
---
|
||
|
||
## 9. 分阶段实施计划(开发期,本节为后续开发用)
|
||
|
||
- **阶段 0 · 数据源 POC(约 1 周)**:对贵阳 4 类 + gzrsks SPA 做可行性验证,拿到真实接口/选择器,确认近两年可回溯性。**POC 不过则方案需调整。**
|
||
- **阶段 1 · 数据模型 + 贵阳 MVP(公务员/事业单位)**:建表、Go 爬虫适配器(A 类优先)、基础列表 API、admin 列表页。
|
||
- **阶段 2 · 全量历史回溯**:跑近两年全量,去重与字段校准,人工抽检。
|
||
- **阶段 3 · 增量 + Bark 每日推送**:调度器 + 推送器 + 订阅过滤 + 失败告警。
|
||
- **阶段 4 · admin 可视化与分析**:仪表盘、趋势图、筛选增强、爬虫运维面板、权限接入。
|
||
- **阶段 5 · 扩展**:国企/央企源、私企二期、全省 9 市州、搜索/收藏/导出。
|
||
|
||
每阶段结束有"冒烟验证 + 数据抽检报告",再进下一阶段(契合你一贯的"非侵入、最小改动、迭代"偏好)。
|
||
|
||
---
|
||
|
||
## 10. 需你拍板的关键问题(Decision Points)
|
||
|
||
1. **私企范围**:首批只做官方/半官方(公务员/事业/国企/央企),私企放二期——可以吗?
|
||
2. **Bark**:先公共 `api.day.app` 跑通,还是直接自建?(需你提供 APNs 证书或授权我部署)
|
||
3. **爬虫形态**:纯 Go 适配器(推荐,运维面小)还是 Python 微服务(SPA 处理强)?
|
||
4. **存储**:复用 service 库 还是 独立 recruitment 库?
|
||
5. **默认推送时间**:每天早上几点?(建议 08:00)
|
||
6. **是否要移动端适配 admin**:还是推送里给深链、电脑看详情即可?
|
||
7. **推送粒度**:每日汇总早报,还是"有新公告实时推"?(建议每日汇总,避免打扰)
|
||
|
||
---
|
||
|
||
## 11. 附录:接口草图(仅供讨论)
|
||
|
||
```
|
||
GET /api/service/admin/recruitment/list?region=贵阳&category=2&from=2026-08-01&q=教师
|
||
GET /api/service/admin/recruitment/stats?range=30d
|
||
GET /api/service/admin/recruitment/sources # 爬虫源状态
|
||
POST /api/service/admin/recruitment/crawl/trigger # 手动触发
|
||
POST /api/service/admin/recruitment/push/test # 测试 Bark
|
||
```
|
||
|
||
---
|
||
*本文档为设计稿,待你确认决策点后进入阶段 0 POC。*
|