e0d9c4e434
- 硬性预筛门槛: 外贸经验必须(仅工作经历匹配), 培养类拦截, 毕业2020-2026, 年龄<=35 - 七维评分+动态阈值+打招呼纪律 - Hermes每日自动化: daily-runner(09:30-18:00)/daily-report/enforce-cutoff/stop-tasks - v10.4: 每累计200人自动刷新页面 - 修正: CDP端口9222(反向隧道), 通知只发私聊(防串台), hr2任务禁用 - WSL端: cdp-tunnel.sh 浏览器工人守护
235 lines
9.7 KiB
Markdown
Executable File
235 lines
9.7 KiB
Markdown
Executable File
# 双账号筛选 — Chrome + Edge 方案 (v0.2 已实施)
|
||
|
||
## 背景
|
||
|
||
两个智联招聘账号同时筛选简历,扩大覆盖面和打招呼配额。
|
||
|
||
## 方案选型
|
||
|
||
| 对比项 | 双 Chrome 实例 | Chrome + Edge |
|
||
|--------|---------------|---------------|
|
||
| profile 隔离 | 手动 robocopy 一份 profile | **天然隔离**,各用各的 |
|
||
| 登录互踢风险 | 同浏览器同协议,有风险 | **不同浏览器,cookie 完全隔离,不会互踢** |
|
||
| 启动方式 | 要记哪个是哪个 | 桌面图标一目了然 |
|
||
| CDP 连接 | playwright connectOverCDP | **完全相同**,脚本零改动 |
|
||
| 脚本改动 | 零差异 | 零差异 |
|
||
|
||
**结论:Chrome + Edge 方案更优,已采用。**
|
||
|
||
## 架构
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ Linux (Hermes) │
|
||
│ │
|
||
│ batch-runner (ACCOUNT=hr1) ─CDP_PORT=9223──→ SSH 9223→9222 │
|
||
│ batch-runner (ACCOUNT=hr2) ─CDP_PORT=9225──→ SSH 9225→9224 │
|
||
│ │
|
||
│ recruitment.db (candidates.account 区分来源) │
|
||
└──────────────────────────────────────────────────────────┘
|
||
│ │
|
||
SSH 隧道 9223→9222 SSH 隧道 9225→9224
|
||
│ │
|
||
┌────────┴──────────┐ ┌────────┴──────────┐
|
||
│ Windows 桌面 │ │ Windows 桌面 │
|
||
│ Chrome (hr1) │ │ Edge (hr2) │
|
||
│ CDP :9222 │ │ CDP :9224 │
|
||
│ user-data-dir: │ │ user-data-dir: │
|
||
│ C:\temp\ │ │ C:\temp\ │
|
||
│ chrome-debug │ │ edge-debug │
|
||
└───────────────────┘ └───────────────────┘
|
||
```
|
||
|
||
## 端口映射
|
||
|
||
| 账号 | 浏览器 | Windows CDP | Linux 本地 | SSH 隧道 |
|
||
|------|--------|------------|-----------|---------|
|
||
| hr1 | Chrome | 9222 | 9223 | `sshpass -p 'xxx' ssh -fN -p 7022 -L 9223:127.0.0.1:9222 sshadmin@8.152.213.143` |
|
||
| hr2 | Edge | 9224 | 9225 | `sshpass -p 'xxx' ssh -fN -p 7022 -L 9225:127.0.0.1:9224 sshadmin@8.152.213.143` |
|
||
|
||
## Edge 配置
|
||
|
||
### 安装路径(已确认)
|
||
|
||
```
|
||
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
|
||
```
|
||
|
||
### user-data-dir
|
||
|
||
```
|
||
C:\temp\edge-debug
|
||
```
|
||
|
||
首次使用无需从默认 profile 复制,Edge 会在该目录创建新 profile。手动登录第二个智联账号后,登录态自动保存在此目录。
|
||
|
||
### 桌面快捷方式(已创建 ✅)
|
||
|
||
桌面路径:`C:\Users\sshadmin.WIN-3NKO8I5R9IJ\Desktop\Edge Debug Mode.lnk`
|
||
|
||
创建方法(通过 scp + cscript):
|
||
1. 本地写 VBS 脚本到 `/tmp/mksc.vbs`
|
||
2. `scp /tmp/mksc.vbs sshadmin@8.152.213.143:\"C:/temp/mksc.vbs\"`
|
||
3. `sshpass -p 'xxx' ssh -p 7022 sshadmin@8.152.213.143 "cscript //nologo C:\\temp\\mksc.vbs"`
|
||
|
||
> ⚠️ 桌面实际路径是 `C:\Users\sshadmin.WIN-3NKO8I5R9IJ\Desktop`(非 `Administrator`),通过 `ws.SpecialFolders("Desktop")` 自动获取正确路径。
|
||
|
||
### ⚠️ CDP 启动方式
|
||
|
||
**SSH 会话内直接启动 Edge → CDP 端口不可达**(Windows Session 隔离)。
|
||
|
||
**解决方案:schtasks 计划任务**
|
||
```powershell
|
||
# 注册(只需一次)
|
||
schtasks /Create /IT /RU Administrator /TN LaunchEdgeDebug /TR "\"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe\" --remote-debugging-port=9224 --user-data-dir=C:\temp\edge-debug" /SC ONLOGON /RL HIGHEST
|
||
|
||
# 每次启动
|
||
schtasks /Run /TN LaunchEdgeDebug
|
||
```
|
||
`/IT` = Interactive,在交互式桌面 session 中运行。详见 `windows-remote-scraping.md`。
|
||
|
||
## 数据库改造(已完成 ✅)
|
||
|
||
```sql
|
||
ALTER TABLE candidates ADD COLUMN account TEXT DEFAULT 'hr1';
|
||
ALTER TABLE greet_log ADD COLUMN account TEXT DEFAULT 'hr1';
|
||
CREATE INDEX idx_cand_account ON candidates(account);
|
||
```
|
||
|
||
现有 2817 条 hr1 数据自动标记 `hr1`。脚本通过 `ACCOUNT` 环境变量写入该字段,查询时按 `account` 过滤。
|
||
|
||
## 脚本改造(已完成 ✅)
|
||
|
||
### zhaopin-scrape.js v9.2
|
||
|
||
改动点:
|
||
1. `const ACCOUNT = process.env.ACCOUNT || 'hr1'` — 文件顶部
|
||
2. CREATE TABLE 加 `account TEXT NOT NULL DEFAULT 'hr1'`
|
||
3. `upsertCandidate()` — INSERT 加 account 列和参数
|
||
4. `logGreet()` — INSERT 加 account 列和参数
|
||
5. `getExistingFingerprints()` — `WHERE account = ?` 过滤
|
||
6. 启动快速跳过指纹加载 — `WHERE account = ?` 过滤
|
||
|
||
### batch-runner.js v2 (多账号版)
|
||
|
||
改动点:
|
||
1. `ACCOUNT`/`CDP_PORT`/`TARGET_CITY` 均从环境变量读取(默认 hr1/9223/郑州)
|
||
2. `runBatch()` 传 `ACCOUNT=xxx` 给子进程
|
||
3. `generateBatchReport()` — 按 account 过滤
|
||
4. `generateFinalReport()` — 所有 13 处 SQL 加 `WHERE account = ?`
|
||
5. `getDbCount()` — 按 account 过滤
|
||
6. 汇报标题带 `[hr1]`/`[hr2]` 标识
|
||
|
||
### 运行方式
|
||
|
||
```bash
|
||
# hr1(Chrome)
|
||
ACCOUNT=hr1 CDP_PORT=9223 node zhaopin-scrape.js 50
|
||
ACCOUNT=hr1 CDP_PORT=9223 nohup node batch-runner.js > /tmp/batch-runner-hr1.log 2>&1 &
|
||
|
||
# hr2(Edge)
|
||
ACCOUNT=hr2 CDP_PORT=9225 node zhaopin-scrape.js 50
|
||
ACCOUNT=hr2 CDP_PORT=9225 nohup node batch-runner.js > /tmp/batch-runner-hr2.log 2>&1 &
|
||
```
|
||
|
||
## Cron 定时任务(已创建 ✅)
|
||
|
||
| 任务 | 时间 | 账号 | 说明 |
|
||
|------|------|------|------|
|
||
| 工作日简历筛选 hr1 | 周一至周五 09:50 | hr1/Chrome/9223 | 原 cron 更新,加 ACCOUNT=hr1 |
|
||
| 工作日简历筛选 hr2 | 周一至周五 09:55 | hr2/Edge/9225 | 新建,错开 5 分钟避免 DB 锁争用 |
|
||
|
||
两个任务错开 5 分钟,避免同时启动时的数据库竞争。各自独立汇报到飞书群。
|
||
|
||
## 汇报规则
|
||
|
||
两个账号**各自独立汇报**,标题带 `[hr1]`/`[hr2]` 标识。`recruitment-report` 查询时按 `account` 过滤。如需汇总两个账号,去掉 account 过滤条件。
|
||
|
||
## SSH 隧道保活配置(2026-06-01 修复)⚠️ 关键
|
||
|
||
SSH 隧道频繁断连的根因:**客户端和服务端都没有心跳保活**。空闲连接被网络/NAT 丢弃后,batch-runner 的 `getChatCount()` 读到 null,误判为"聊天耗尽"并发群汇报。
|
||
|
||
**客户端保活(Linux `~/.ssh/config`):**
|
||
```
|
||
Host windows-hr
|
||
HostName 8.152.213.143
|
||
Port 7022
|
||
User sshadmin
|
||
ServerAliveInterval 15
|
||
ServerAliveCountMax 3
|
||
TCPKeepAlive yes
|
||
ExitOnForwardFailure yes
|
||
StrictHostKeyChecking no
|
||
```
|
||
|
||
**服务端保活(Windows `C:\ProgramData\ssh\sshd_config`):**
|
||
```
|
||
TCPKeepAlive yes
|
||
ClientAliveInterval 30
|
||
ClientAliveCountMax 3
|
||
```
|
||
修改后需重启 sshd:`net stop sshd && net start sshd`
|
||
|
||
**两端必须同时配置**,仅客户端保活在 Windows OpenSSH 上不可靠。
|
||
|
||
### 建隧道命令
|
||
```bash
|
||
# 外网连接(通过内网穿透),需 sshpass 密码认证
|
||
sshpass -p 'xxx' ssh -fN -p 7022 -L 9223:127.0.0.1:9222 sshadmin@8.152.213.143
|
||
sshpass -p 'xxx' ssh -fN -p 7022 -L 9225:127.0.0.1:9224 sshadmin@8.152.213.143
|
||
```
|
||
|
||
### 验证隧道
|
||
```bash
|
||
ss -tlnp | grep -E "9223|9225" # 确认端口监听
|
||
curl -s http://127.0.0.1:9223/json/version | head -1 # 确认 CDP 可达
|
||
curl -s http://127.0.0.1:9225/json/version | head -1
|
||
```
|
||
|
||
### 隧道守护脚本(自动重连)
|
||
|
||
心跳保活只能降低断连概率,无法 100% 防止。`ssh-tunnel-watchdog.sh` 作为兜底,每 10 秒检测端口,断了自动重建:
|
||
|
||
```bash
|
||
# 启动(与 batch-runner 同时运行)
|
||
nohup /home/kt/scripts/ssh-tunnel-watchdog.sh > /tmp/ssh-tunnel-watchdog.log 2>&1 &
|
||
```
|
||
|
||
脚本路径:`/home/kt/scripts/ssh-tunnel-watchdog.sh`
|
||
监控端口:9223(hr1)、9225(hr2)
|
||
日志:`/tmp/ssh-tunnel-watchdog.log`(仅断连重连时有输出)
|
||
|
||
## batch-runner.js 聊天耗尽验证机制(2026-06-01 新增)
|
||
|
||
batch-runner.js 现在内置三层防护,防止误判"聊天耗尽":
|
||
|
||
### 1. getChatCount() 区分 CDP 状态
|
||
- 返回数字:正常读取到聊天次数
|
||
- 返回 `null`:CDP 可达但页面读取失败(弹窗遮挡等)
|
||
- 返回 `'cdp_down'`:CDP 端口不通(隧道断开/浏览器关闭)
|
||
- 通过 `net.createConnection` 先探测端口,5秒超时
|
||
|
||
### 2. verifyChatExhausted(reason) 二次确认
|
||
所有 5 个判定点(启动、主循环、子进程 chat_empty、批次后检查×2)都调用此函数:
|
||
- CDP 不通 → 等待 30 秒重试,连续 3 次 CDP 不通 → 判定"连接异常"(**不发**最终汇报)
|
||
- 读到 0 → 连续 3 次确认后才判定真正耗尽
|
||
- 读到 >0 → 判定误判,返回剩余次数继续运行
|
||
|
||
### 3. stopReason 控制最终汇报
|
||
- `chat_empty`:聊天真正耗尽 → ✅ 发最终汇报
|
||
- `cdp_down`:连接异常 → ❌ **不发**汇报,只发"CDP 连接断开"错误通知
|
||
- `normal`:正常结束 → 不发汇报
|
||
|
||
## 日常启动流程
|
||
|
||
1. Windows 桌面:双击「Chrome Debug」→ 打开智联推荐页(hr1)
|
||
2. Windows 桌面:双击「Edge Debug Mode」→ 打开智联推荐页(hr2)
|
||
3. Linux:确认两条 SSH 隧道都通(`ss -tlnp | grep -E "9223|9225"` + `curl http://127.0.0.1:9223/json/version`)
|
||
4. Linux:启动隧道守护(`nohup /home/kt/scripts/ssh-tunnel-watchdog.sh > /tmp/ssh-tunnel-watchdog.log 2>&1 &`)
|
||
5. Linux:两个 batch-runner 并行启动(或等 cron 自动启动)
|
||
|
||
## 已知问题
|
||
|
||
1. ~~SSH 隧道不稳定~~(2026-06-01 已修复:双向心跳保活)
|
||
2. ~~CDP 连接失败与聊天耗尽共用退出路径~~(2026-06-01 已修复:verifyChatExhausted + stopReason)
|