diff --git a/API文档.md b/API文档.md index 7628007..837d317 100644 --- a/API文档.md +++ b/API文档.md @@ -549,7 +549,22 @@ Set-Cookie: auth_token=a1b2c3d4e5f6...; HttpOnly; Max-Age=31536000; SameSite=Lax | task_type | 说明 | 必要参数 | 返回 result | |-----------|------|---------|-------------| | `check_login` | 检测浏览器环境中 BOSS 账号是否已登录 | `account_name`(环境名) | `{ "browser_id", "browser_name", "boss_username", "is_logged_in" }` | -| `boss_recruit` | 执行 BOSS 直聘自动招聘流程 | `worker_id` + `params` | 根据任务定义返回 | +| `boss_recruit` | 执行 BOSS 直聘自动招聘流程 | `worker_id` + `params` | `{ "job_title", "total_processed", "wechat_collected", "phone_collected", "details", "error_count" }` | + +`boss_recruit` 的 `details` 项示例: + +```json +{ + "name": "候选人A", + "job": "Python开发", + "wechat": "wxid_xxx", + "phone": "13800138000" +} +``` + +说明: +- 若自动化流程发生报错,任务状态会标记为 `failed`(不再显示为 `success`)。 +- 失败任务也会保留 `result`,便于在任务列表查看已采集到的微信号/手机号数量。 --- diff --git a/server/core/task_dispatcher.py b/server/core/task_dispatcher.py index 60d146b..8524900 100644 --- a/server/core/task_dispatcher.py +++ b/server/core/task_dispatcher.py @@ -144,6 +144,7 @@ class TaskDispatcher: if failure_reason: task.status = TaskStatus.FAILED task.error = failure_reason + task.result = result else: task.status = TaskStatus.SUCCESS task.result = result diff --git a/worker/tasks/boss_recruit.py b/worker/tasks/boss_recruit.py index 4b582f9..e903dbe 100644 --- a/worker/tasks/boss_recruit.py +++ b/worker/tasks/boss_recruit.py @@ -95,26 +95,41 @@ class BossRecruitHandler(BaseTaskHandler): human_delay(2.5, 4.0) # 4. 执行招聘流程 - collected = self._recruit_flow(tab, job_title, max_greet) + flow_result = self._recruit_flow(tab, job_title, max_greet) + collected = flow_result["details"] + errors = flow_result["errors"] - return { + wechat_set = {str(c.get("wechat", "")).strip() for c in collected if str(c.get("wechat", "")).strip()} + phone_set = {str(c.get("phone", "")).strip() for c in collected if str(c.get("phone", "")).strip()} + + has_errors = bool(errors) + result = { "job_title": job_title, "total_processed": len(collected), - "wechat_collected": sum(1 for c in collected if c.get("wechat")), + "wechat_collected": len(wechat_set), + "phone_collected": len(phone_set), "details": collected, + "error_count": len(errors), + "errors": errors[:20], + "success": not has_errors, } + if has_errors: + result["error"] = f"招聘流程出现 {len(errors)} 处错误" - def _recruit_flow(self, tab, job_title: str, max_greet: int) -> List[dict]: + return result + + def _recruit_flow(self, tab, job_title: str, max_greet: int) -> dict: """核心招聘流程:遍历聊天列表,打招呼、询问微信号、收集结果。""" greeting = f"您好,我们正在招【{job_title}】,看到您的经历比较匹配,方便简单聊聊吗?" ask_wechat = "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。" collected = [] + errors = [] # 获取左侧会话列表 items = self._get_conversation_items(tab) if not items: self.logger.warning("未找到会话列表元素") - return collected + return {"details": collected, "errors": ["未找到会话列表元素"]} total = min(len(items), max_greet) self.logger.info("会话数约 %d,本次处理前 %d 个", len(items), total) @@ -164,18 +179,22 @@ class BossRecruitHandler(BaseTaskHandler): messages = self._get_chat_messages(tab) ctx = self._analyze_context(messages, job_title) wechats = ctx["wechats"][:2] + phones = ctx["phones"][:2] collected.append({ "name": name, "job": job_title, "wechat": wechats[0] if wechats else "", + "phone": phones[0] if phones else "", }) except Exception as e: - self.logger.error("处理第 %d 个会话出错: %s", i + 1, e) + err_msg = f"处理第 {i + 1} 个会话出错: {e}" + self.logger.error(err_msg) + errors.append(err_msg) continue - return collected + return {"details": collected, "errors": errors} # ─── 辅助方法 ─── @@ -305,14 +324,18 @@ class BossRecruitHandler(BaseTaskHandler): full_boss = " ".join(boss_texts) wechats = [] + phones = [] for t in friend_texts: wechats.extend(self._extract_wechat(t)) + phones.extend(self._extract_phone(t)) wechats = list(dict.fromkeys(wechats))[:3] + phones = list(dict.fromkeys(phones))[:3] return { "already_greeting": job_title in full_boss or "招" in full_boss, "already_asked_wechat": "微信" in full_boss or "微信号" in full_boss, "wechats": wechats, + "phones": phones, } @staticmethod @@ -333,3 +356,18 @@ class BossRecruitHandler(BaseTaskHandler): if s and s not in found and len(s) >= 6: found.append(s) return found[:3] + + @staticmethod + def _extract_phone(text: str) -> list: + """提取手机号(仅保留 11 位中国大陆手机号)。""" + if not text or not text.strip(): + return [] + + found = [] + # 支持 13800138000 / 138-0013-8000 / 138 0013 8000 等格式 + raw_candidates = re.findall(r"1[3-9][\d\-\s]{9,15}", text) + for raw in raw_candidates: + digits = re.sub(r"\D", "", raw) + if len(digits) == 11 and digits.startswith("1") and digits not in found: + found.append(digits) + return found[:3]