Jhatchi/Cyber-Job-Hunter
GitHub: Jhatchi/Cyber-Job-Hunter
自动化网络安全职位聚合器,通过个人资料评分优化求职流程。
Stars: 0 | Forks: 0
# 网络安全求职猎手
基于个人资料评分的自动化网络安全职位聚合器,配有实时 Streamlit 仪表板。在 BeCode 布鲁塞尔蓝队与红队训练营期间独立构建,目标是获得 2026 年 9 月的实习机会。
[](https://github.com/Jhatchi/Cyber-Job-Hunter/actions/workflows/ci.yml)
[](#项目指标)
[](#项目指标)
[](pyproject.toml)
[](pyproject.toml)
[](pyproject.toml)
[](LICENSE)
[](https://www.linkedin.com/in/johan-emmanuel-hatchi/)
## 截图

## 功能
- **爬取 18 个网络安全职位来源**,覆盖比利时、卢森堡和欧盟(大型咨询公司、专业网络安全公司、公共部门、ENISA、远程职位聚合器)。
- **为每个职位评分 0 到 100 分**,基于可调的个人资料(目标职位、资历、语言、位置),并提供逐行分解说明分数缘由。
- **在 Streamlit 仪表板中呈现结果**,支持 CSV 导出,具备“自上次运行以来新增”的检测功能以及 10 多种筛选器。
## 技术栈
**核心:** Python 3.11+, httpx, BeautifulSoup4, lxml, feedparser, pydantic v2, SQLModel (SQLite), loguru, click
**HTTP 缓存:** hishel (ETag, Last-Modified)
**仪表板:** Streamlit, pandas
**质量保障:** pytest + respx, ruff (带 bandit `S` 选择器), mypy strict, GitHub Actions CI
## 快速开始
```
git clone https://github.com/Jhatchi/Cyber-Job-Hunter.git && cd Cyber-Job-Hunter
python3.11 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
#### python scripts/init_db.py && python scripts/run_scrape.py && streamlit run dashboard/app.py
Dashboard at `http://localhost:8501`.
## 项目指标
| Metric | Value |
|---|---|
| Python LOC (`src` + `tests` + `dashboard` + `scripts`) | 12 257 |
| Tests | 357 passing |
| Coverage on `src/` | 89% (Streamlit UI excluded) |
| Active scrapers | 18 across 6 categories |
| Type safety | mypy `strict = true` |
| Security lint | ruff with `S` (bandit) selector |
| CI | GitHub Actions: ruff + mypy + pytest on every push |
Run locally:
```bash
pytest --cov=src --cov-report=term
#### 运行 ruff check . && mypy src
## 架构
```
config/ (profile.yaml + sources.yaml)
|
v
BaseScraper (抽象基类)
速率限制,抖动,指数退避,
断路器,robots.txt,机器人检测
|
+----------+-----------+
v v
REST / RSS / Workday HTML 爬虫
| |
+----------+-----------+
v
JobBase (Pydantic v2)
|
v
filters.py (拒绝规则,网络安全相关性门控)
|
v
scoring.py (0-100分,含可解释的分解说明)
|
v
storage.py (基于 SQLModel 的 SQLite,SHA-256 去重)
|
+------+-------+
v v
#### CSV 导出 Streamlit 仪表板
`BaseScraper` 中集中了反滥用逻辑:每个爬虫(REST、RSS、Workday、HTML)都无需重复即可继承速率限制、退避、断路器和 `robots.txt` 解析。新增来源仅需实现其特定领域的解析逻辑。
## 评分引擎
每个职位根据可调的个人资料 (`config/profile.yaml`) 评分 0 到 100 分。分数是**可解释的**:仪表板的详情标签页会显示每条触发的规则,包括匹配的关键词和拒绝原因。
**主要信号:**
- `+30` 目标职位匹配(SOC 分析师,IAM,渗透测试员,GRC 初级,...)
- `+15` 初级 / 实习生 / 培训生 / 0-2 年经验
- `+10` 布鲁塞尔地区,或“毕业生项目”
- `+5` 每个技术关键词(跨 7 个网络安全类别,上限 `+30`)
**扣分与拒绝条件:**
- `-20` “必须硕士”且无替代方案
- 自动拒绝:`5年以上经验`,高级 / 主管 / 经理级别,要求荷兰语 B2+ 但无英语或法语后备,既无目标职位也无技术关键词(网络安全相关性门控)
**延迟来源**(记录在 `config/sources.yaml` 中):CCB 和 EGov Select(Akamai 反机器人)、cybersecurity.lu(React SPA,无公开 JSON)、Spotit、Moovijob.lu(Cloudflare)、CERT-EU(需欧盟 SECRET 安全许可)、LinkedIn(计划加入,注意服务条款)。
## 反滥用与伦理
职位信息是公开数据,但负责任地爬取它们并非易事。集中处理于 `BaseScraper`:
- **遵守 `robots.txt`**:每次抓取前通过 `urllib.robotparser` 检查。
- **诚实 `User-Agent`**:标识项目,并附带专用的 Proton Pass 联系人别名(可撤销)。
- **速率限制**:每个域名 2 到 5 秒,加上随机抖动。
- **指数退避**:针对瞬时错误:5 秒、15 秒、45 秒(最多 3 次重试),然后触发断路器。
- **域名断路器**:连续 3 次 4xx 或 5xx 错误会禁用该来源 1 小时。
- **检测 Cloudflare 和验证码**:通过单词边界正则表达式,遇到则干净中止(无重试风暴)。
- **对终止性 4xx 不重试**(404,403 当非机器人相关时)。
- **分页上限**:可配置每个来源(默认 5)。
- **默认禁用 LinkedIn 和 Indeed**。
聚合器不收集申请人或招聘人员的个人数据。SQLite 数据库保存在本地。无第三方分析,无遥测数据。
## 已知限制
- **无 JavaScript 渲染。** Cloudflare 保护或完全客户端渲染的来源(Moovijob.lu、cybersecurity.lu、Spotit、EGov Select)已延迟。添加 Playwright 可解决,但会增加 CI 复杂性和运行时间:这是有意的权衡,而非疏忽。
- **Streamlit UI 未纳入覆盖率计算。** 89% 的覆盖率适用于 `src/`。仪表板小部件是手动测试的。添加 `streamlit-testing` 在待办事项中,但优先级低于发布新爬虫。
- **评分是基于规则的,非机器学习。** 权重根据用户个人资料手动调整。计划增加点赞/点踩反馈循环和机器学习评分(Sprint 4)。
- **单一个人资料,本地 SQLite。** 无多用户,无远程数据库。设计为个人工具,非 SaaS。迁移到 Postgres + 多个人资料是增量功能,但超出当前范围。
- **地理范围:比利时、卢森堡、欧盟机构、远程。** 未覆盖法国/荷兰/德国。添加容易(新增 YAML 条目),只是当前焦点不在此。
- **暂无警报功能。** 新职位会在仪表板中显示,但无邮件或推送通知。Gmail SMTP 摘要配合 launchd cron 是下一个里程碑(Sprint 3)。
## 路线图
- ✅ **Sprint 1** (2026 年 4 月):项目初始化,Pydantic 模型,评分引擎,过滤器,SQLite 存储,4 个爬虫。
- ✅ **Sprint 2** (2026 年 4 月):Streamlit 仪表板,“自上次运行以来新增”检测,14 个额外爬虫(Smals, Cream, Travaillerpour, Actiris, Accenture, KPMG, Capgemini, Orange Cyberdefense, Devoteam, Sopra Steria, Nexova, EPAM, Toreon, ENISA),网络安全相关性门控。
- 🚧 **Sprint 3**:通过 launchd cron 的 Gmail SMTP 摘要,Forem, StepStone, Jobat(若服务条款允许),Workday Proximus。
- 🚧 **Sprint 4**:Anthropic 驱动的求职信草稿,带安全措施的 LinkedIn 数据接入,基于点赞/点踩反馈训练的机器学习评分。
## 项目结构
```
Cyber-Job-Hunter/
pyproject.toml ruff, mypy strict, pytest config
requirements.txt
.env.example
config/ profile.yaml, sources.yaml
src/
models.py Job, ScoreResult, ScrapeRun
config.py Pydantic loaders
filters.py rejection rules, cyber relevance gate
scoring.py 0-100 with explainable breakdown
deduplication.py SHA-256 content hash
storage.py JobRepository (SQLite)
scrapers/ base.py + 18 concrete scrapers
dashboard/ Streamlit app, 3 views
scripts/ init_db.py, run_scrape.py, export_csv.py
#### tests/ 357 测试, respx mocks
## 贡献指南
Personal portfolio project, but issues and PRs are welcome. Code conventions in [`CONTRIBUTING.md`](CONTRIBUTING.md).
## 许可证
[MIT](LICENSE), 2026 Jhatchi.
## 关于
Built solo by **Johan-Emmanuel Hatchi** ([GitHub](https://github.com/Jhatchi) · [LinkedIn](https://www.linkedin.com/in/johan-emmanuel-hatchi/)) during the [BeCode Brussels](https://becode.org) Blue & Red Team bootcamp (November 2025 to September 2026). Open to cybersecurity internship opportunities starting September 2026 in Belgium.
```
详情与统计视图
 
####
## 来源
18 个活跃的爬虫,分为 6 个类别:
| 类别 | 来源 |
|---|---|
| **大型咨询公司与 ESN** | KPMG, Capgemini, Sopra Steria, Accenture, Devoteam, EPAM |
| **专业网络安全公司** | NVISO, Toreon, Orange Cyberdefense, EASI, Nexova, Cream |
| **比利时公共部门** | Smals, Actiris, Travaillerpour |
| **欧盟机构** | ENISA |
| **聚合器** | Remotive |
| **其他比利时科技公司** | itsme |
爬取技术涵盖 REST JSON、RSS、Workday CXS、Next.js `_next/data`、XML 站点地图和纯 HTML。每个来源在 [`config/sources.yaml`](config/sources.yaml) 中有自己的配置块。
完整规则集
+30 目标职位匹配(SOC 分析师,IAM,渗透测试员,GRC 初级,等等) +15 “初级、实习生、培训生、0-2年经验” +10 标题中包含“年轻毕业生” 或 描述中包含“毕业生项目” +5 每个匹配的技术关键词(上限 +30),7个网络安全类别 +10 布鲁塞尔 +5 瓦隆区、卢森堡、比利时-卢森堡后备选项 +10 法语 + 英语 +8 仅英语 +8 仅法语 +5 荷兰语“优先考虑” -5 “要求学士”且无替代方案 -20 “必须硕士”且无替代方案 -10 “3年以上经验” 拒绝(分数 = 0): - “5年以上经验”、高级、主管、经理、首席、团队负责人 - 要求荷兰语 B2/C1/C2 且无英语或法语替代方案 - 佛兰德地区但未提及“仅需英语” #### - 网络安全相关性门控:既无目标职位也无技术关键词包含技术与国家/地区的完整来源表
| 来源 | 类型 | 国家/地区 | 备注 | |---|---|---|---| | [Remotive](https://remotive.com) | REST JSON | 远程 | 严格服务条款:4 次请求/天,24 小时延迟,需注明来源。 | | [NVISO](https://nviso.eu/jobs/) | HTML | BE, DE, GR, AT | 专业网络安全公司,2026年4月离开 Recruitee。 | | [itsme](https://itsme-id.com) | Recruitee API | BE | 布鲁塞尔数字身份平台。 | | [EASI](https://easi.net/en/jobs) | HTML | BE | ESN,瓦隆区和佛兰德地区。 | | [Smals](https://www.smals.be/en/jobs/list) | HTML (Drupal) | BE | 比利时社会保障 ICT 服务。 | | [Cream by Audensiel](https://www.creamconsulting.com/jobs) | HTML | LU | 网络安全 ESN,卢森堡。 | | [Travaillerpour.be](https://travaillerpour.be) | HTML (Drupal) | BE | 联邦职位门户(FOD, SPF, NCCN)。 | | [Actiris](https://www.actiris.brussels) | XML sitemap + HTML | BE | 布鲁塞尔就业服务,每次运行获取最近 40 个职位。 | | [Accenture](https://www.accenture.com/be-en/careers) | Workday CXS API | BE | 已应用比利时筛选条件。 | | [KPMG Belgium](https://kpmg-career.talent-soft.com) | RSS (TalentSoft) | BE | 完整源,在下游进行网络安全过滤。 | | [Capgemini](https://www.capgemini.com/be-en/jobs) | REST (Azure) | BE | 已预设 `search=cyber`。 | | [Orange Cyberdefense](https://jobs.orangecyberdefense.com) | HTML (TeamTailor) | BE, EU | 职位列表加上每个职位的详细信息补充。 | | [Devoteam](https://www.devoteam.com/jobs) | REST (GCP Cloud Talent) | BE | 原生国家筛选器。 | | [Sopra Steria](https://careers.soprasteria.be) | HTML (Attrax) | BE | 详情页的 JSON-LD `JobPosting`。 | | [Nexova Group](https://www.nexovagroup.eu) | HTML | BE | 网络安全与国防,ESA-Redu SOC。 | | [EPAM](https://careers.epam.com/en/jobs/belgium) | Next.js `_next/data` | BE | 从 `__NEXT_DATA__` 动态提取构建 ID。 | | [Toreon](https://www.toreon.com/jobs/) | HTML | BE | 专业网络安全咨询,安特卫普总部。 | | [ENISA](https://www.enisa.europa.eu/careers) | HTML | EU | 欧盟网络安全机构,雅典总部。 |标签:DNS解析, HTTP缓存, Kubernetes, Python开发, Python编程, SQLite, Streamlit仪表板, Web scraping, 前端仪表板, 安全职位, 安全规则引擎, 实习项目, 实时更新, 开发实践, 开源情报, 开源项目, 数据导出, 数据库管理, 数据缓存, 数据聚合, 欧盟职位, 求职工具, 测试覆盖, 用户配置文件, 网络安全, 网络抓取, 网页解析, 职位猎手, 职位聚合, 自动化抓取, 蓝队红队, 评分系统, 过滤器, 运行时操纵, 逆向工具, 隐私保护