ha'ha
This commit is contained in:
17
API文档.md
17
API文档.md
@@ -549,7 +549,22 @@ Set-Cookie: auth_token=a1b2c3d4e5f6...; HttpOnly; Max-Age=31536000; SameSite=Lax
|
|||||||
| task_type | 说明 | 必要参数 | 返回 result |
|
| task_type | 说明 | 必要参数 | 返回 result |
|
||||||
|-----------|------|---------|-------------|
|
|-----------|------|---------|-------------|
|
||||||
| `check_login` | 检测浏览器环境中 BOSS 账号是否已登录 | `account_name`(环境名) | `{ "browser_id", "browser_name", "boss_username", "is_logged_in" }` |
|
| `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`,便于在任务列表查看已采集到的微信号/手机号数量。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ class TaskDispatcher:
|
|||||||
if failure_reason:
|
if failure_reason:
|
||||||
task.status = TaskStatus.FAILED
|
task.status = TaskStatus.FAILED
|
||||||
task.error = failure_reason
|
task.error = failure_reason
|
||||||
|
task.result = result
|
||||||
else:
|
else:
|
||||||
task.status = TaskStatus.SUCCESS
|
task.status = TaskStatus.SUCCESS
|
||||||
task.result = result
|
task.result = result
|
||||||
|
|||||||
@@ -95,26 +95,41 @@ class BossRecruitHandler(BaseTaskHandler):
|
|||||||
human_delay(2.5, 4.0)
|
human_delay(2.5, 4.0)
|
||||||
|
|
||||||
# 4. 执行招聘流程
|
# 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,
|
"job_title": job_title,
|
||||||
"total_processed": len(collected),
|
"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,
|
"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}】,看到您的经历比较匹配,方便简单聊聊吗?"
|
greeting = f"您好,我们正在招【{job_title}】,看到您的经历比较匹配,方便简单聊聊吗?"
|
||||||
ask_wechat = "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。"
|
ask_wechat = "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。"
|
||||||
collected = []
|
collected = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
# 获取左侧会话列表
|
# 获取左侧会话列表
|
||||||
items = self._get_conversation_items(tab)
|
items = self._get_conversation_items(tab)
|
||||||
if not items:
|
if not items:
|
||||||
self.logger.warning("未找到会话列表元素")
|
self.logger.warning("未找到会话列表元素")
|
||||||
return collected
|
return {"details": collected, "errors": ["未找到会话列表元素"]}
|
||||||
|
|
||||||
total = min(len(items), max_greet)
|
total = min(len(items), max_greet)
|
||||||
self.logger.info("会话数约 %d,本次处理前 %d 个", len(items), total)
|
self.logger.info("会话数约 %d,本次处理前 %d 个", len(items), total)
|
||||||
@@ -164,18 +179,22 @@ class BossRecruitHandler(BaseTaskHandler):
|
|||||||
messages = self._get_chat_messages(tab)
|
messages = self._get_chat_messages(tab)
|
||||||
ctx = self._analyze_context(messages, job_title)
|
ctx = self._analyze_context(messages, job_title)
|
||||||
wechats = ctx["wechats"][:2]
|
wechats = ctx["wechats"][:2]
|
||||||
|
phones = ctx["phones"][:2]
|
||||||
|
|
||||||
collected.append({
|
collected.append({
|
||||||
"name": name,
|
"name": name,
|
||||||
"job": job_title,
|
"job": job_title,
|
||||||
"wechat": wechats[0] if wechats else "",
|
"wechat": wechats[0] if wechats else "",
|
||||||
|
"phone": phones[0] if phones else "",
|
||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
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
|
continue
|
||||||
|
|
||||||
return collected
|
return {"details": collected, "errors": errors}
|
||||||
|
|
||||||
# ─── 辅助方法 ───
|
# ─── 辅助方法 ───
|
||||||
|
|
||||||
@@ -305,14 +324,18 @@ class BossRecruitHandler(BaseTaskHandler):
|
|||||||
full_boss = " ".join(boss_texts)
|
full_boss = " ".join(boss_texts)
|
||||||
|
|
||||||
wechats = []
|
wechats = []
|
||||||
|
phones = []
|
||||||
for t in friend_texts:
|
for t in friend_texts:
|
||||||
wechats.extend(self._extract_wechat(t))
|
wechats.extend(self._extract_wechat(t))
|
||||||
|
phones.extend(self._extract_phone(t))
|
||||||
wechats = list(dict.fromkeys(wechats))[:3]
|
wechats = list(dict.fromkeys(wechats))[:3]
|
||||||
|
phones = list(dict.fromkeys(phones))[:3]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"already_greeting": job_title in full_boss or "招" in full_boss,
|
"already_greeting": job_title in full_boss or "招" in full_boss,
|
||||||
"already_asked_wechat": "微信" in full_boss or "微信号" in full_boss,
|
"already_asked_wechat": "微信" in full_boss or "微信号" in full_boss,
|
||||||
"wechats": wechats,
|
"wechats": wechats,
|
||||||
|
"phones": phones,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -333,3 +356,18 @@ class BossRecruitHandler(BaseTaskHandler):
|
|||||||
if s and s not in found and len(s) >= 6:
|
if s and s not in found and len(s) >= 6:
|
||||||
found.append(s)
|
found.append(s)
|
||||||
return found[:3]
|
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]
|
||||||
|
|||||||
Reference in New Issue
Block a user