首页 / 博客 / 场景·私域·运营

招聘 HR 微信自动加候选人与初筛机器人实现方案

分类:场景·私域·运营 · 标签:招聘、微信自动加好友、HR

前言

招聘旺季,HR 每天要在微信上处理数以百计的候选人联系请求——手动搜索微信号、发送好友申请、回复初筛问题,这些重复操作占据了大量精力,而真正有价值的面试沟通和人才评估反而被压缩。

本文从工程角度出发,介绍如何利用微信 HTTP 接口构建一套自动化的候选人添加与初筛机器人流程:HR 从 ATS(招聘管理系统)或 Excel 名单中导出候选人微信号,系统自动按频率安全地发送好友申请;候选人通过验证后,机器人立即推送标准化初筛问卷,并根据关键词回答完成第一轮意向识别,最终把合格候选人标记为"待电话确认"状态推给 HR。整套流程把 HR 从重复的微信操作里解放出来,让人专注于判断而非执行。


一、整体架构与流程设计

1.1 核心流程

候选人名单(Excel/ATS导出)
        ↓
   [名单解析模块]
   读取微信号、职位、来源
        ↓
   [好友申请队列]
   按安全频率逐批发申请
        ↓
   [回调监听服务]
   监听好友通过事件
        ↓
   [初筛问卷推送]
   发送标准化问题集
        ↓
   [回答解析模块]
   关键词匹配 + 意向评分
        ↓
   [结果写入 ATS/钉钉/飞书]
   合格候选人推送给 HR

1.2 技术选型

模块技术
语言Python 3.10+
任务队列Celery + Redis
数据库SQLite(小规模)/ PostgreSQL(规模化)
回调服务FastAPI
微信接口HTTP REST API
部署云服务器(需公网 IP 接收回调)

二、环境准备与接口初始化

2.1 基础配置

pythonimport requests
import time
import random

BASE  = "https://你的接口域名"   # 注册后在官方文档获取
TOKEN = "你的Token"
APPID = "你的appId"
HEADERS = {"token": TOKEN}       # 鉴权字段名以官方文档为准

# 代码为示例,具体接口/字段以官方文档为准

2.2 设置消息回调地址

系统收到候选人回复时,微信接口会把消息 POST 到我们预先设置的公网地址。回调设置只需调用一次:

pythondef set_callback(callback_url: str):
    payload = {
        "appId": APPID,
        "callbackUrl": callback_url
    }
    resp = requests.post(
        f"{BASE}/setCallback",
        json=payload,
        headers=HEADERS
    )
    result = resp.json()
    if result.get("ret") == 200:
        print(f"回调设置成功: {callback_url}")
    else:
        print(f"设置失败: {result}")
    return result

# 部署后调用一次
set_callback("https://你的服务器域名/wechat/callback")

三、候选人好友申请模块

3.1 防封频率策略

招聘场景中批量添加好友是高风险操作,需要严格遵守频率限制,否则账号会被微信限制。以下是实践中总结的安全策略:

时间维度推荐上限说明
每天总量5~15 个新号从 5 个起步,稳定账号≤15
每 2 小时≤5 个不要集中在某一时段
单次间隔随机 3~8 分钟避免机械规律
新账号先在线 3 天新微信号激活后至少在线 3 天再批量操作

这些限制不是为了规避检测而刻意设置的"伪随机",而是模拟真实 HR 的工作节奏——真人每天也不可能加几十个陌生人,合理的频率才是长期可用的保障。

为什么要严格控制每日上限?

微信对账号的行为模式有持续监测,添加陌生好友的频率、验证语的文本相似度、账号的"年龄"(注册时间与活跃历史)都是触发风控的因素。新注册或刚换设备的账号尤其脆弱,初期应以手动操作为主,让账号积累正常的社交行为记录,再逐步引入自动化。实操建议是:同一批候选人申请应分散在多个工作日发送,验证语每次适度变化,避免完全一致的模板文本触发机器行为识别。

此外,HR 账号还应保持正常的日常使用行为,例如与同事、朋友正常聊天,参与公司内部群讨论等,这些真实的社交行为有助于维持账号健康评分。

3.2 好友申请实现

pythonimport time
import random
from typing import Optional

def add_candidate(wxid: str, remark: str, job_title: str) -> dict:
    """
    向候选人发送好友申请
    wxid: 候选人微信号
    remark: 验证语,建议包含职位和来源
    job_title: 职位名称,用于本地记录
    """
    payload = {
        "appId": APPID,
        "wxId": wxid,
        "remark": remark,   # 好友申请验证语
        "addType": 1        # 字段含义以官方文档为准
    }
    resp = requests.post(
        f"{BASE}/addContacts",
        json=payload,
        headers=HEADERS
    )
    result = resp.json()
    print(f"[添加] {wxid} | {job_title} | ret={result.get('ret')}")
    return result


def batch_add_candidates(candidates: list, daily_limit: int = 10):
    """
    批量添加候选人,带频率控制
    candidates: [{"wxid": "...", "job": "...", "source": "..."}]
    """
    today_count = 0
    for item in candidates:
        if today_count >= daily_limit:
            print(f"已达今日上限 {daily_limit},停止")
            break

        wxid = item["wxid"]
        job  = item.get("job", "")
        source = item.get("source", "招聘平台")

        remark = f"您好,我是XX公司 HR,在{source}看到您的简历,诚邀了解{job}职位,期待认识!"

        add_candidate(wxid, remark, job)
        today_count += 1

        # 随机等待 3~8 分钟
        wait_sec = random.randint(180, 480)
        print(f"  等待 {wait_sec}s 后继续...")
        time.sleep(wait_sec)

    print(f"本次共发送申请: {today_count} 个")

3.3 从 Excel 读取候选人名单

pythonimport pandas as pd

def load_candidates_from_excel(file_path: str) -> list:
    """
    读取候选人名单
    Excel 列:微信号、姓名、职位、来源渠道、是否已发申请
    """
    df = pd.read_excel(file_path)
    # 过滤已处理的行
    pending = df[df["是否已发申请"].isna() | (df["是否已发申请"] == "")]
    candidates = []
    for _, row in pending.iterrows():
        candidates.append({
            "wxid": str(row["微信号"]).strip(),
            "name": str(row["姓名"]),
            "job":  str(row["职位"]),
            "source": str(row.get("来源渠道", "招聘平台"))
        })
    return candidates

Excel 名单维护建议

Excel 作为候选人名单的管理载体,需要注意几个细节:微信号字段在 Excel 中有时会被自动识别为数字格式,导致开头的零或特殊字符丢失,读取时应统一转为字符串并去除首尾空格(代码中已处理)。"是否已发申请"列建议在发送成功后立即写回 Excel,防止程序中断重跑时重复发送同一候选人。如果名单来自 ATS 系统导出,最好在导出环节就加入去重逻辑,避免同一候选人因为投递多个职位而被重复添加。


四、好友通过事件监听与初筛触发

4.1 回调服务(FastAPI)

当候选人通过好友申请,微信接口会把事件 POST 到我们设置的回调地址。以下是监听服务的核心逻辑:

pythonfrom fastapi import FastAPI, Request
import json

app = FastAPI()

# 简单的上下文存储(生产环境建议用 Redis)
pending_survey = {}   # {wxid: {"job": ..., "step": 0, "answers": []}}

SURVEY_QUESTIONS = [
    "您好!感谢通过好友验证 😊 请问您目前在职还是离职状态?",
    "您期望的到岗时间大约是什么时候?",
    "您的期望薪资范围是多少(月薪)?",
    "请问您目前在哪个城市?是否接受异地?"
]

@app.post("/wechat/callback")
async def wechat_callback(request: Request):
    body = await request.json()
    # 字段名以官方文档为准,下面仅作示例
    event_type = body.get("type")
    from_wxid  = body.get("fromWxid")
    content    = body.get("content", "")
    app_id     = body.get("appId")

    # 好友通过事件(event_type 值以官方文档为准)
    if event_type in ("friend_accept", 10000):
        handle_friend_accept(from_wxid)

    # 普通文本消息
    elif event_type in ("text", 1):
        handle_text_message(from_wxid, content)

    return {"code": 200}  # 必须返回 200,否则平台会重试


def handle_friend_accept(wxid: str):
    """好友通过后,立即发送第一个问题"""
    pending_survey[wxid] = {"step": 0, "answers": []}
    send_message(wxid, SURVEY_QUESTIONS[0])


def handle_text_message(wxid: str, content: str):
    """接收候选人回答,推进问卷流程"""
    if wxid not in pending_survey:
        return  # 不在初筛流程中,忽略

    state = pending_survey[wxid]
    step  = state["step"]
    state["answers"].append(content)

    next_step = step + 1
    if next_step < len(SURVEY_QUESTIONS):
        # 还有问题,继续问
        state["step"] = next_step
        time.sleep(random.randint(3, 8))  # 模拟真人思考
        send_message(wxid, SURVEY_QUESTIONS[next_step])
    else:
        # 问卷完成,评分并通知 HR
        finalize_survey(wxid, state["answers"])
        del pending_survey[wxid]

4.2 发送消息

pythondef send_message(to_wxid: str, content: str) -> dict:
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "content": content
    }
    resp = requests.post(
        f"{BASE}/message/postText",
        json=payload,
        headers=HEADERS
    )
    return resp.json()
    # 代码为示例,具体接口/字段以官方文档为准

问卷设计注意事项

初筛问卷的问题数量建议控制在 4~6 题,问题之间逻辑递进,不要一次抛出所有问题。每道题发送前加入短暂的随机延迟(3~8 秒),模拟真人打字的节奏,避免候选人感觉在和机器人对话而产生反感。问题措辞应当友好、简洁,避免过于正式或让人觉得在填表。薪资、到岗时间等敏感信息放在后几题,先用轻松的在职状态问题暖场,有助于提升候选人的回复率。

对于长时间没有回复的候选人,建议在 24 小时后发送一条温和的提醒消息,超过 48 小时无回复则标记为"待人工跟进",由 HR 决定是否主动电话联系。


五、初筛评分与结果推送

5.1 意向评分逻辑

初筛机器人收集到候选人的回答后,需要做简单的意向判断,避免把明显不符合的候选人推给 HR:

pythondef score_candidate(answers: list) -> dict:
    """
    简单评分逻辑,实际项目可接入 LLM 做语义理解
    answers: [在职状态回答, 到岗时间回答, 薪资回答, 城市回答]
    """
    score = 0
    flags = []

    if len(answers) < 4:
        return {"score": 0, "flags": ["问卷未完成"], "pass": False}

    # 在职/离职状态
    status_ans = answers[0]
    if "离职" in status_ans or "裸辞" in status_ans:
        score += 30  # 离职状态到岗更快
        flags.append("离职-到岗快")
    elif "在职" in status_ans:
        score += 20
        flags.append("在职")

    # 到岗时间
    arrive_ans = answers[1]
    if any(k in arrive_ans for k in ["一周", "两周", "马上", "随时", "1周", "2周"]):
        score += 30
        flags.append("到岗快")
    elif any(k in arrive_ans for k in ["一个月", "1个月", "月内"]):
        score += 20
        flags.append("一个月内")
    elif "三个月" in arrive_ans or "3个月" in arrive_ans:
        score += 5
        flags.append("到岗慢")

    # 薪资(简单判断是否提了明确数字)
    salary_ans = answers[2]
    if any(c.isdigit() for c in salary_ans):
        score += 20
        flags.append("薪资明确")
    else:
        flags.append("薪资模糊")

    # 城市意愿
    city_ans = answers[3]
    if "接受" in city_ans or "可以" in city_ans or "没问题" in city_ans:
        score += 20
        flags.append("异地接受")

    return {
        "score": score,
        "flags": flags,
        "pass": score >= 60,
        "raw_answers": answers
    }

5.2 结果通知 HR

pythondef finalize_survey(wxid: str, answers: list):
    result = score_candidate(answers)

    # 告知候选人问卷已完成
    if result["pass"]:
        send_message(wxid, "感谢您的回答!我们的 HR 将在 1 个工作日内与您进一步沟通,请保持微信畅通 😊")
    else:
        send_message(wxid, "感谢您的参与!目前的岗位与您的情况可能还需进一步评估,我们会在有合适机会时第一时间联系您。")

    # 推送给 HR(示例:发消息到 HR 微信或企业内部群)
    hr_wxid = "HR的微信号"
    flag_str = "、".join(result["flags"])
    hr_msg = (
        f"【初筛完成】候选人 {wxid}\n"
        f"评分:{result['score']} | 标签:{flag_str}\n"
        f"结论:{'✅ 建议跟进' if result['pass'] else '⚠️ 暂缓'}\n"
        f"-----\n"
        f"回答摘要:\n"
        + "\n".join([f"Q{i+1}: {a}" for i, a in enumerate(answers)])
    )
    send_message(hr_wxid, hr_msg)

    print(f"[初筛完成] {wxid} | 得分={result['score']} | pass={result['pass']}")

评分策略的扩展方向

上述评分逻辑是基于关键词的规则匹配,适合快速验证方案可行性。实际招聘场景中,候选人的回答往往表达方式多样,例如"下周就能来"和"随时都行"表达相同的意思,但规则匹配未必能都覆盖。可以在此基础上引入大语言模型做语义理解,将候选人的自由文本回答转换为结构化字段(在职状态、到岗周期、薪资区间、城市),再套用评分规则,准确率会显著提升。此外,评分阈值(当前设为 60 分)应根据实际招聘岗位的供需情况调整,供不应求的岗位可适当降低门槛,避免过滤掉潜在合适的候选人。


六、关于托管 HTTP 接口的选型说明

上述所有示例调用的是微信 HTTP REST 接口。这类接口通常由第三方平台提供——用手机或云端设备扫码登录微信后,通过接口代理实现好友添加、消息收发、群管理等操作,开发者只需发 HTTP 请求,不需要处理微信私有协议的逆向工程。

WechatApi 提供扫码登录、消息收发、好友与群管理等 REST 接口,HTTP 调用即可,适合作为本文方案的接口层选项。

接入这类平台前,建议关注以下几点:

  1. 合规用途:接口仅用于本人账号的合法业务,不得用于群发广告、骚扰用户或违反微信用户协议的场景。
  2. 账号隔离:招聘账号专号专用,不要和个人微信混用。
  3. 数据安全:候选人信息属于个人数据,存储和传输需符合相关法规要求。
  4. 频率合规:严格遵守上文提到的加好友频率限制,避免账号被封。

七、部署与运维要点

7.1 服务器配置

回调服务需要部署在有公网 IP 且 80/443 端口可访问的服务器上。国内服务器还需要域名备案。推荐使用 HTTPS,部分接口平台强制要求回调地址必须是 HTTPS。

bash# 使用 uvicorn 启动 FastAPI 回调服务
uvicorn callback_server:app --host 0.0.0.0 --port 8080

# 生产环境建议用 nginx 反代 + SSL

服务稳定性保障

回调服务是整个自动化流程的枢纽,一旦中断,候选人的通过事件和消息回复都会丢失,无法重新触发。因此需要配置进程守护(如 supervisor 或 systemd),在服务异常退出时自动重启。同时建议在服务启动时检查微信账号的在线状态,若账号掉线则立即告警通知 HR,避免在无感知的情况下漏接候选人消息。

对于 pending_survey 状态存储,小规模场景下用内存字典即可,但进程重启后状态会丢失——正在进行中的问卷会中断。生产环境建议迁移到 Redis,设置合理的过期时间(如 48 小时),并在服务启动时从 Redis 恢复状态。

7.2 异常处理

pythondef safe_send(wxid: str, content: str, retry: int = 3) -> bool:
    """带重试的消息发送"""
    for i in range(retry):
        try:
            result = send_message(wxid, content)
            if result.get("ret") == 200:
                return True
            print(f"发送失败 ret={result.get('ret')},第{i+1}次重试")
            time.sleep(5)
        except Exception as e:
            print(f"异常: {e},第{i+1}次重试")
            time.sleep(10)
    return False

7.3 常见问题排查

问题可能原因处理方式
好友申请发出但对方收不到账号被限频检查今日添加数量,降低频率
回调收不到消息服务器公网不可达检查防火墙/安全组,确认端口开放
消息发送接口报错微信账号离线检查扫码登录状态
初筛问题没有回复候选人未看消息设置 24h 超时逻辑,标记为"待人工跟进"

总结

通过将微信 HTTP 接口与任务队列、回调事件驱动相结合,可以构建出一套相对完整的招聘候选人自动化触达流程——从批量好友申请到初筛问卷推送,再到评分结果通知 HR,整条链路在保持合理频率的前提下,能够显著降低 HR 在重复微信操作上花费的时间,让招聘工作聚焦在真正需要人判断的环节。

自动化不是替代 HR 的判断力,而是把 HR 从"发消息、等回复、记录数据"这类机械操作中解放出来。初筛机器人过滤的是明显不符合的候选人,对于评分接近边界的情况,建议仍由 HR 人工核查,避免因规则过死而错失合适人才。整套方案的核心价值在于把 HR 的精力集中到面试沟通和最终决策上,而不是让机器完全替代人的判断。

想动手试试?

WechatApi 提供扫码登录、消息收发、好友与群管理等 REST 接口,注册后几分钟跑通。

立即免费注册查看开发文档

相关产品页

🔗 微信机器人开发(产品页)🔗 微信群管理机器人(产品页)🔗 微信API接口对接(产品页)

相关文章

开源微信框架 vs 托管微信API,到底怎么选微信 SCRM 系统怎么搭建?技术方案详解私域流量自动化运营怎么做(微信侧实战)微信自动化营销获客实战(合规版)
© 2025 WechatApi · 企业级微信智能机器人接入平台
官网价格帮助文档博客
苏ICP备2024128799号 · 苏ICP备2023038368号