This commit is contained in:
ddrwode
2026-03-06 13:51:32 +08:00
parent f98c848b60
commit 1f935096c2

View File

@@ -64,8 +64,19 @@ class BossRecruitHandler(BaseTaskHandler):
greet_target = self._parse_positive_int(params.get("greet_target"), default=20)
position_names = self._normalize_string_list(params.get("position_names"))
# 年龄范围(程序内过滤,不在浏览器筛选中点击)
age_min = self._parse_optional_int(params.get("age_min"))
age_max = self._parse_optional_int(params.get("age_max"))
self.ensure_not_cancelled(cancel_event)
await progress_cb(task_id, f"正在启动招聘流程,目标打招呼人数: {greet_target}")
age_desc = ""
if age_min is not None and age_max is not None:
age_desc = f",年龄范围: {age_min}-{age_max}"
elif age_min is not None:
age_desc = f",最小年龄: {age_min}"
elif age_max is not None:
age_desc = f",最大年龄: {age_max}"
await progress_cb(task_id, f"正在启动招聘流程,目标打招呼人数: {greet_target}{age_desc}")
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(
@@ -79,6 +90,8 @@ class BossRecruitHandler(BaseTaskHandler):
greet_target,
worker_id,
cancel_event,
age_min,
age_max,
)
return result
@@ -94,6 +107,8 @@ class BossRecruitHandler(BaseTaskHandler):
greet_target: int,
worker_id: str,
cancel_event,
age_min: Optional[int] = None,
age_max: Optional[int] = None,
) -> Dict[str, Any]:
self.ensure_not_cancelled(cancel_event)
@@ -109,6 +124,8 @@ class BossRecruitHandler(BaseTaskHandler):
worker_id=worker_id,
account_name=account_name,
cancel_event=cancel_event,
age_min=age_min,
age_max=age_max,
)
errors = flow.get("errors", [])
return {
@@ -151,6 +168,8 @@ class BossRecruitHandler(BaseTaskHandler):
worker_id: str,
account_name: str,
cancel_event,
age_min: Optional[int] = None,
age_max: Optional[int] = None,
) -> Dict[str, Any]:
details: List[dict] = []
errors: List[str] = []
@@ -213,6 +232,8 @@ class BossRecruitHandler(BaseTaskHandler):
position_label=label,
default_job=job_title,
cancel_event=cancel_event,
age_min=age_min,
age_max=age_max,
)
if not added:
continue
@@ -367,8 +388,10 @@ class BossRecruitHandler(BaseTaskHandler):
position_label: str,
default_job: str,
cancel_event,
age_min: Optional[int] = None,
age_max: Optional[int] = None,
) -> Tuple[int, List[dict]]:
"""与 1.py _greet_geek_list_skip_greeted 一致的去重逻辑。"""
"""与 1.py _greet_geek_list_skip_greeted 一致的去重逻辑,增加年龄过滤"""
added = 0
records: List[dict] = []
for item in geek_list or []:
@@ -376,6 +399,16 @@ class BossRecruitHandler(BaseTaskHandler):
geek_key = self._geek_key(item)
if not geek_key or geek_key in greeted_keys:
continue
# 年龄过滤:从候选人数据中提取年龄,不满足范围则跳过
if age_min is not None or age_max is not None:
age = self._parse_age(item)
if age is not None:
if age_min is not None and age < age_min:
continue
if age_max is not None and age > age_max:
continue
if not self._greet_one_geek(page, container, item):
continue
@@ -582,3 +615,52 @@ class BossRecruitHandler(BaseTaskHandler):
return parsed if parsed > 0 else default
except Exception:
return default
@staticmethod
def _parse_optional_int(value: Any) -> Optional[int]:
"""解析可选整数None / 空串 / 无效值返回 None。"""
if value is None:
return None
try:
parsed = int(value)
return parsed if parsed > 0 else None
except (TypeError, ValueError):
return None
@staticmethod
def _parse_age(item: dict) -> Optional[int]:
"""
从 geekCard 中提取候选人年龄(数字)。
BOSS 直聘 API 的 geekCard 中可能包含:
- ageDesc: "25岁"
- age: 25
- geekAge: 25
返回整数年龄,无法解析则返回 None。
"""
import re
card = item.get("geekCard") or {}
# 优先使用 ageDesc如 "25岁"
age_desc = str(card.get("ageDesc", "") or "").strip()
if age_desc:
match = re.search(r"(\d+)", age_desc)
if match:
return int(match.group(1))
# 尝试 age 字段
age_val = card.get("age")
if age_val is not None:
try:
return int(age_val)
except (TypeError, ValueError):
pass
# 尝试 geekAge 字段
geek_age = card.get("geekAge")
if geek_age is not None:
try:
return int(geek_age)
except (TypeError, ValueError):
pass
return None