frangelbarrera/job-hunter
GitHub: frangelbarrera/job-hunter
一个自动化职位抓取与匹配 pipeline,帮助求职者聚合远程招聘信息、评分筛选并借助 LLM 生成个性化求职邮件。
Stars: 4 | Forks: 0
# 求职者
针对安全工程师职位的自动化职位抓取 pipeline。从多个主打远程工作的招聘平台聚合列表,根据目标 profile 对其进行评分,并在 LLM 的辅助下起草个性化求职信。
[](https://github.com/frangelbarrera/job-hunter/actions/workflows/ci.yml)
[](https://github.com/frangelbarrera/job-hunter/actions/workflows/scrape.yml)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://docs.astral.sh/ruff/)
## 功能
- **多源抓取** — RemoteOK、HackerNews "Ask HN: Who is hiring?",并提供可插拔的接口以接入新来源
- **Profile 匹配** — 根据 YAML profile 对每个招聘信息进行评分(0–1),以确保维持较低的底噪
- **LLM 辅助求职信** — 通过 Gemini(以 Groq 作为后备)使用严格的模板起草陌生开发邮件
- **定时执行** — GitHub Actions 每 6 小时在公共 runner 上运行一次,无本地带宽消耗
- **自包含** — 输出为单个 JSON 文件,您可以随时随地使用 grep、管道操作或导入
- **无 PII** — 抓取工具仅存储公开的职位元数据,绝不持久化存储任何申请人数据
## 架构
```
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Actions (cron 6h) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ RemoteOK │ │ HackerNews │ │ (pluggable)│ │
│ │ scraper │ │ scraper │ │ scrapers │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └──────────┬────────┴───────────────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ utils.save() │ → data/jobs.json (deduped) │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ git push
▼
┌─────────────────────────────────────────────────────────────────┐
│ Local laptop (manual) │
│ │
│ git pull → match_score.py → generate_email.py → review → send │
│ │
│ LLM: Gemini API (primary) → Groq API (fallback) │
│ Mail: Gmail API (read-only + send scopes only) │
└─────────────────────────────────────────────────────────────────┘
```
## 快速开始
```
git clone https://github.com/frangelbarrera/job-hunter.git
cd job-hunter
pip install -r requirements-dev.txt
cp .env.example .env # then edit .env with your keys
cp profile.yaml.example profile.yaml # then edit with your details
pytest # should pass green
python -m scrapers.remoteok
python -m scrapers.hackernews
cat data/jobs.json | python -m json.tool | head -40
```
## 配置
### 环境变量 (`.env`)
| 变量 | 用途 | 是否必须 |
|---|---|---|
| `GEMINI_API_KEY` | 主 LLM(用于陌生邮件草稿) | `generate_email.py` 需要 |
| `GROQ_API_KEY` | 后备 LLM | `generate_email.py` 需要 |
| `GMAIL_CREDENTIALS_PATH` | OAuth `credentials.json` 路径 | `scripts/send_email.py` 需要 |
| `GMAIL_TOKEN_PATH` | 缓存的 `token.json` 路径 | `scripts/send_email.py` 需要 |
| `PROFILE_PATH` | 包含您目标 profile 的 YAML | 默认为 `profile.yaml` |
### Profile (`profile.yaml`)
一个用于描述您目标职位的 YAML 文件。匹配评分器会使用它来为招聘信息加权。
```
# 完整模板请参见 profile.yaml.example
target_title: Security Engineer
seniority: junior # junior | mid | senior
remote_only: true
stack: [python, typescript, fastapi, react]
domains: [security, osint, ics, ml]
keywords:
- security
- python
- remote
- junior
exclude_keywords:
- senior
- lead
- manager
```
## 使用说明
### 抓取(通过 GitHub Actions 自动执行)
工作流 `.github/workflows/scrape.yml` 每 6 小时运行一次。您也可以从 Actions 标签页手动触发它,或者在本地运行:
```
python -m scrapers.remoteok
python -m scrapers.hackernews
```
结果将存入 `data/jobs.json`(已去重,保留最后 1000 条记录)。
### 评分和排序
```
python -m scripts.match_score
# 打印前 20 个匹配项到 stdout
# 写入 data/ranked_jobs.json 以供后续使用
```
### 起草陌生邮件
```
python -m scripts.generate_email --top 5
# 打印 5 封草拟邮件到 stdout,保存前会要求确认
# 草稿保存至 data/drafts/ (gitignored)
```
### 发送(可选,需要设置 Gmail API)
```
python -m scripts.send_email --dry-run # prints what would be sent
python -m scripts.send_email # actually sends, requires confirmation per email
```
## 项目结构
```
job-hunter/
├── .github/
│ ├── workflows/
│ │ ├── ci.yml # lint + test on push & PR
│ │ └── scrape.yml # scheduled scraping every 6h
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .pre-commit-config.yaml
├── .env.example
├── LICENSE
├── README.md
├── CONTRIBUTING.md
├── SECURITY.md
├── pyproject.toml
├── requirements.txt
├── requirements-dev.txt
├── profile.yaml.example
├── scrapers/
│ ├── __init__.py
│ ├── base.py # ScraperProtocol + shared types
│ ├── remoteok.py
│ ├── hackernews.py
│ └── utils.py # save_jobs(), dedupe(), load_profile()
├── scripts/
│ ├── __init__.py
│ ├── match_score.py
│ ├── generate_email.py
│ └── send_email.py
├── data/
│ └── .gitkeep
└── tests/
├── __init__.py
├── conftest.py
├── test_remoteok.py
├── test_hackernews.py
└── test_match_score.py
```
## 安全
请参阅 [SECURITY.md](SECURITY.md)。简短版本:切勿提交密钥,抓取工具不存储任何 PII,并且 Gmail 集成仅请求 `gmail.send` + `gmail.readonly` 权限。
## 许可证
MIT — 详见 [LICENSE](LICENSE)。
## 免责声明
本工具仅限个人使用,用于抓取公开可用的招聘信息。它不会绕过身份验证、违反服务条款 (ToS),也不会试图欺骗招聘平台。自动化发送邮件由用户自行承担责任 — 请遵守 CAN-SPAM(美国)、GDPR(欧盟)以及您当地的法律法规。不要做垃圾邮件发送者。
标签:BeEF, GitHub Actions, LLM集成, Python, Sysdig, 安全规则引擎, 无后门, 求职助手, 爬虫, 网络调试, 自动化, 自动笔记, 逆向工具