christopherdraper/linkedin-easy-apply

GitHub: christopherdraper/linkedin-easy-apply

一个由 Claude AI 驱动的自动化求职工具,通过三级任务队列实现跨 LinkedIn 及多 ATS 平台的职位搜索、评分、求职信生成与智能表单填写。

Stars: 0 | Forks: 0

# job-apply 跨 LinkedIn Easy Apply 及外部 ATS 平台(Greenhouse、Workday、Ashby、Lever、SmartRecruiters、Paylocity、Workable、Comeet、PageUp)的自动化求职搜索与申请工具,由 Claude 提供支持。 一个三级队列会逐步升级处理任务: - **Q1 (batch)** 搜索 LinkedIn,根据你的个人资料对每个职位发布进行评分,生成量身定制的求职信,并通过 Easy Apply 或导航外部 ATS 表单进行提交。 - **Q2 (autonomous retry)** 提取 Q1 中分数超过阈值的失败申请,并结合 Playwright 以及 Claude 页面分析进行重试。处理邮箱验证码(Gmail IMAP)、验证码(2captcha 或 capsolver)以及特定 ATS 的异常情况。 - **Q3 (escalation)** 将 Q2 无法完成的任务通过 Web 仪表板呈现,并提供预先计算好的答案,以便你在不到一分钟内手动完成申请。 Flask 仪表板会跟踪市场职位发布量、每份申请的报告以及 Q2/Q3 队列。 有关日常操作,请参阅 [USAGE.md](USAGE.md)。有关内部架构,请参阅 [CLAUDE.md](CLAUDE.md)。 ## 使用 Claude Code 进行设置(推荐) 如果你已经安装了 [Claude Code](https://claude.com/claude-code),最快的方法是让它驱动设置过程。 1. Clone 该代码仓库并 `cd` 进入其中。 2. 在该目录下打开 Claude Code。 3. 粘贴此 prompt: ## 环境要求 - Python 3.9+ - 一个 LinkedIn 账户 - 一个 Anthropic API key (https://console.anthropic.com) - 可选但推荐: - 带有 App Password 的 Gmail 账户(用于 ATS 邮箱验证码) - 2captcha 或 capsolver API key(用于 ATS 验证码挑战) - 一个 SOCKS5 住宅代理(仅在针对 SmartRecruiters / Incapsula WAF 时需要) ## 安装说明 ``` # 1. Clone repo git clone https://github.com/christopherdraper/linkedin-easy-apply cd linkedin-easy-apply # 2. Install Python dependencies pip install -r requirements.txt # or: pip install playwright anthropic python-docx flask # 3. Install Playwright 使用的 Chromium build playwright install chromium ``` ## 首次运行指南 最快上手的方法是让 Claude 从你的简历中引导生成你的个人资料。 ### 第 1 步:创建运行时目录并复制个人资料模板 ``` mkdir -p ~/.local/share/job-apply cp profile_template.json ~/.local/share/job-apply/profile.json ``` ### 第 2 步:让 Claude 根据你的简历填写个人资料 在代码仓库目录中打开 Claude Code。放入你的简历(PDF 或 .docx),并向它提供以下 prompt: Claude 将生成一份完整的 `profile.json`。在继续之前请大致检查一遍。这份个人资料是所有表单填充的唯一事实来源,因此准确的 `screening_answers` 键比其他任何事情都重要。 ### 第 3 步:设置你的环境变量 请参阅下方的 [环境变量清单](#environment-variable-checklist)。 ### 第 4 步:捕获 LinkedIn 会话 LinkedIn 会将会话 cookie 绑定到你登录时的 IP 地址,因此请从运行脚本的同一台机器上进行登录。运行一次此命令: ``` python -c " from playwright.sync_api import sync_playwright from pathlib import Path session_file = Path.home() / '.local/share/job-apply/sessions/linkedin.json' session_file.parent.mkdir(parents=True, exist_ok=True) with sync_playwright() as p: browser = p.chromium.launch(headless=False) context = browser.new_context() page = context.new_page() page.goto('https://www.linkedin.com/login') input('Log in in the browser, then press Enter...') context.storage_state(path=str(session_file)) browser.close() " ``` 如果你是在一台 headless 服务器上运行,请安装 Xvfb 外加一个 VNC server,将 `DISPLAY=:99` 指向虚拟显示器,并通过 VNC 运行相同的代码片段。会话每隔几周就会过期。当脚本报告会话过期时重新运行此命令。 ### 第 5 步:进行一次 dry run 不会提交任何内容。确认评分、求职信生成和表单发现功能正常工作。 ``` python job_search_apply.py --title "Senior DevOps Engineer" --dry-run ``` 检查输出。你应该能看到找到的职位、AI 评分、生成到 `~/.local/share/job-apply/cover-letters/` 的求职信,以及记录到 `~/.local/share/job-apply/applications.json` 的决策。 ### 第 6 步:首次正式批次执行 从小规模开始。五份申请,保守的阈值。 ``` python job_search_apply.py --max-applications 5 --min-score 0.75 ``` ### 第 7 步:启动仪表板 ``` python dashboard.py # http://localhost:5050 ``` 仪表板会显示市场职位发布量、带有匹配分数的申请历史记录、每个申请的审计页面、Q2/Q3 队列、成本统计和面试跟踪。完整参考请见 [DASHBOARD.md](DASHBOARD.md)。 ### 第 8 步:处理 Q2 队列 匹配分数超过 0.70 阈值的 Q1 失败申请会自动排入 Q2。使用 autonomous retry agent 处理它们: ``` python assisted_apply_mcp.py --max 10 ``` 这就是完整的日常周期。 ## 环境变量清单 唯一需要的环境变量是 Anthropic key。其他所有内容都存在于 `profile.json` 中,从而保持其作为唯一事实来源。 | 变量 | 必需 | 用途 | |----------|----------|---------| | `ANTHROPIC_API_KEY` | 是 | AI 评分、表单填充、求职信 | ``` echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.bashrc source ~/.bashrc ``` ### 基于个人资料的凭据 这些信息存在于 `profile.json` 的 `application_settings` 下,而不是作为环境变量。 | 字段 | 适用场景 | 获取方式 | |-------|-------------|---------------| | `gmail_app_password` | Greenhouse 和 PageUp 邮箱验证码 | Google 账号,安全,两步验证,App Passwords。为“Mail”生成一个。16 个字符,无空格。 | | `captcha_api_key` | Lever (hCaptcha)、Eightfold (reCAPTCHA)、部分 Workday | 在 2captcha.com 或 capsolver.com 注册。添加额度。 | | `captcha_service` | 同上 | `"2captcha"` 或 `"capsolver"`。默认为 `2captcha`。 | | `proxy_rules` | SmartRecruiters (Incapsula WAF)。在其他情况下可选。 | `domain: socks5://host:port` 的字典。示例:`{"smartrecruiters.com": "socks5://127.0.0.1:1080"}`。 | | `auto_create_accounts` | Workday 账号 | 布尔值。为 true 时,bot 会创建 ATS 账号并在本地存储凭据。 | | `max_applications_per_day` | 总是 | 每日申请硬性上限。默认 10。可通过 `--max-applications` 覆盖单次运行的设置。 | | `min_match_score` | 总是 | AI 匹配分数的底线(0.0 到 1.0)。代码中默认为 0.30,个人资料模板中为 0.75。可通过 `--min-score` 覆盖单次运行的设置。 | `profile.json` 中的示例代码块: ``` "application_settings": { "max_applications_per_day": 50, "min_match_score": 0.75, "gmail_app_password": "xxxxxxxxxxxxxxxx", "captcha_api_key": "abcd1234...", "captcha_service": "2captcha", "auto_create_accounts": true, "proxy_rules": { "smartrecruiters.com": "socks5://127.0.0.1:1080" } } ``` ## 运行 ``` # 始终先进行 dry-run python job_search_apply.py --title "Senior SRE" --dry-run # 针对你 profile 中的每个 title 进行 Live batch python job_search_apply.py --max-applications 50 --min-score 0.75 # Market snapshot(按 title 统计 postings 数量,无 applications) python job_search_apply.py --market-snapshot # 单个 external URL(bypasses LinkedIn) python job_search_apply.py --external-url https://boards.greenhouse.io/company/jobs/123 # Q2 autonomous retry python assisted_apply_mcp.py --max 20 python assisted_apply_mcp.py --list # show queue python assisted_apply_mcp.py --job-id li_abc # retry a specific entry # Dashboard python dashboard.py # http://localhost:5050 ``` ### 常用参数 (Q1) | 参数 | 默认值 | 描述 | |------|---------|-------------| | `--profile` | `~/.local/share/job-apply/profile.json` | 个人资料路径 | | `--title` | 个人资料中的所有职位 | 搜索单个职位名称 | | `--max-applications` | 来自个人资料 | 限制本次运行的提交数量 | | `--min-score` | 来自个人资料 | 匹配分数底线 | | `--dry-run` | false | 仅评分和记录日志 | | `--external-url` | 无 | 申请单个非 LinkedIn URL | | `--market-snapshot` | false | 统计每个职位的发布数量,不进行申请 | | `--source` | `linkedin` | `linkedin`, `remoteok`, `hn`, `biotech`, `all` | ## 数据存储 所有数据均存储在本地。个人资料内容会发送至 Anthropic API 用于评分和表单填充。没有其他任何数据会离开本机。 | 数据 | 位置 | |------|----------| | 个人资料 | `~/.local/share/job-apply/profile.json` | | LinkedIn 会话 | `~/.local/share/job-apply/sessions/linkedin.json` | | 申请记录 | `~/.local/share/job-apply/applications.json` | | Q2/Q3 队列 | `~/.local/share/job-apply/deep_apply_queue.json` | | 市场快照 | `~/.local/share/job-apply/search_log.json` | | 求职信 | `~/.local/share/job-apply/cover-letters/` | | 失败表单调试转储 | `~/.local/share/job-apply/debug/` | ## 安全特性 - **Dry-run 标志** 允许你测试整个 pipeline 而不进行任何提交。 - **敏感字段中止** 如果表单要求填写 SSN、银行账户、护照或类似信息,会立即中止操作。 - **Prompt 注入检测** 在将职位描述和表单标签传递给 AI 之前对其进行扫描。 - **AI 响应验证** 将生成的答案限制在合理的长度内,并筛查注入内容。 - **已申请跟踪** 通过 `applications.json` 根据 URL 进行去重。 - **每日上限** 防止批处理失控。 ## 接下来去哪 - [USAGE.md](USAGE.md) 涵盖了日常工作流、特定 ATS 说明、队列维护和故障排除。 - [DASHBOARD.md](DASHBOARD.md) 是 Web 仪表板的完整参考(每个部分、每个路由、数据源、面试跟踪)。 - [CLAUDE.md](CLAUDE.md) 是开发者参考:架构、handler 注册表、经验教训和贡献指南。
标签:Claude AI, Playwright, RPA, Web自动化, 求职自动化, 特征检测, 逆向工具