frangelbarrera/job-hunter

GitHub: frangelbarrera/job-hunter

一个自动化职位抓取与匹配 pipeline,帮助求职者聚合远程招聘信息、评分筛选并借助 LLM 生成个性化求职邮件。

Stars: 4 | Forks: 0

# 求职者 针对安全工程师职位的自动化职位抓取 pipeline。从多个主打远程工作的招聘平台聚合列表,根据目标 profile 对其进行评分,并在 LLM 的辅助下起草个性化求职信。 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/frangelbarrera/job-hunter/actions/workflows/ci.yml) [![Scrape](https://static.pigsec.cn/wp-content/uploads/repos/cas/52/5294d5f421cde5f4152ce7d3a68bd7c6abfcc236f4a3f3fd6a19cae06d075581.svg)](https://github.com/frangelbarrera/job-hunter/actions/workflows/scrape.yml) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](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, 安全规则引擎, 无后门, 求职助手, 爬虫, 网络调试, 自动化, 自动笔记, 逆向工具