欢迎光临
我们一直在努力

影刀RPA实操指南:HR场景简历自动筛选与入职流程自动化

影刀RPA实操指南:HR场景简历自动筛选与入职流程自动化

HR的一天,有多少时间花在"操作"上?

我老婆是HR,以前每天晚上回来都跟我抱怨:"今天又看了200份简历,眼睛要瞎了。"我一开始以为是开玩笑,后来她给我看了她的工作流程:

  • 每天打开招聘平台(Boss直聘、智联招聘、前程无忧),一个一个下载新投递的简历PDF
  • 打开每份PDF,看学历、工作经验、期望薪资,手动记到Excel表里
  • 筛选出合适的候选人,发邮件约面试
  • 面试通过后,发入职资料清单,收齐后再一个一个核对
  • 入职当天,把候选人信息录入到OA系统、考勤系统、企业微信
  • 这些操作里,除了"判断简历是否合适"这个决策需要人来做之外,其他全是纯机械操作。一套自动化下来,每天至少能省2-3个小时。

    我之前帮她搭了一套HR自动化系统,从简历采集到入职流程全覆盖。这篇文章把完整方案整理出来,换个行业背景,你可以直接套用到自己的HR工作中。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述


    核心方案:HR自动化五步闭环

    第一步:简历自动采集
    ├── 多平台统一采集(Boss直聘/智联/前程无忧/LinkedIn)
    ├── 批量下载简历PDF
    └── 自动归类存入文件夹

    第二步:简历信息解析与录入
    ├── PDF转文本 + OCR识别关键字段
    ├── 自动写入Excel/飞书招聘管理表
    └── 自动补充候选人评分

    第三步:面试安排自动化
    ├── 自动发送面试邀请邮件/消息
    ├── 自动创建飞书日程
    └── 面试前自动提醒

    第四步:入职材料收集
    ├── 自动发送入职资料清单
    ├── 自动收件追踪
    └── 资料完整度检查

    第五步:多系统录入
    ├── 自动录入OA系统
    ├── 自动开通企业微信
    └── 自动创建飞书账号


    第一步:简历自动采集

    HR在各个招聘平台收到的简历格式、位置都不统一。最实用的方案是从HR的邮箱入手——因为几乎所有招聘平台都会把候选人简历以邮件附件形式推送到HR邮箱。

    邮箱简历采集流程

    # 影刀Python步骤:从邮箱批量下载简历附件
    # 适用:网易邮箱/QQ邮箱/企业邮箱(支持IMAP协议)
    # 前提:已开启邮箱的IMAP服务(在邮箱设置中开启)

    import imaplib
    import email
    from email.header import decode_header
    import os
    import re

    # ========== 配置(从影刀变量读取) ==========
    EMAIL_ADDRESS = GetVar('邮箱地址')
    EMAIL_PASSWORD = GetVar('邮箱授权码') # 不是登录密码,是邮箱设置中生成的授权码
    IMAP_SERVER = GetVar('IMAP服务器') # 如: imap.163.com, imap.qq.com
    SAVE_DIR = GetVar('简历存储目录') # 如: D:/简历库/
    SEARCH_KEYWORDS = ['简历', '应聘', '求职', 'Resume', 'CV']
    # 只处理最近N天的邮件
    DAYS_BACK = int(GetVar('回溯天数'))

    # 确保存储目录存在
    os.makedirs(SAVE_DIR, exist_ok=True)

    # 连接IMAP服务器
    mail = imaplib.IMAP4_SSL(IMAP_SERVER)
    mail.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
    mail.select('INBOX')

    # 搜索指定日期范围的邮件
    from datetime import datetime, timedelta
    since_date = (datetime.now() – timedelta(days=DAYS_BACK)).strftime('%d-%b-%Y')
    result, email_ids = mail.search(None, f'(SINCE "{since_date}")')

    email_id_list = email_ids[0].split()
    downloaded_count = 0

    for email_id in email_id_list:
    result, msg_data = mail.fetch(email_id, '(RFC822)')
    raw_email = msg_data[0][1]
    msg = email.message_from_bytes(raw_email)

    # 解析邮件主题
    subject, encoding = decode_header(msg['Subject'])[0]
    if isinstance(subject, bytes):
    subject = subject.decode(encoding or 'utf-8', errors='ignore')

    # 判断是否是简历邮件
    is_resume_mail = False
    for keyword in SEARCH_KEYWORDS:
    if keyword.lower() in (subject or '').lower():
    is_resume_mail = True
    break

    if not is_resume_mail:
    continue

    # 解析发件人
    from_str = msg.get('From', '')
    # 尝试提取姓名和邮箱
    from_name = ''
    from_email_addr = ''
    match = re.search(r'"?([^"<]*)"?\\s*<([^>]+)>', from_str)
    if match:
    from_name = match.group(1).strip()
    from_email_addr = match.group(2).strip()

    # 遍历附件
    for part in msg.walk():
    if part.get_content_maintype() == 'multipart':
    continue
    if part.get('Content-Disposition') is None:
    continue

    filename = part.get_filename()
    if filename:
    # 解码文件名
    filename, encoding = decode_header(filename)[0]
    if isinstance(filename, bytes):
    filename = filename.decode(encoding or 'utf-8', errors='ignore')

    # 只下载简历格式:PDF/Word
    if not any(filename.lower().endswith(ext) for ext in ['.pdf', '.doc', '.docx']):
    continue

    # 构建保存的文件名:日期_候选人姓名_原文件名
    safe_from_name = re.sub(r'[\\\\/*?:"<>|]', '', from_name or '未知')
    save_name = f"{datetime.now().strftime('%Y%m%d')}_{safe_from_name}_{filename}"
    save_path = os.path.join(SAVE_DIR, save_name)

    # 保存附件
    with open(save_path, 'wb') as f:
    f.write(part.get_payload(decode=True))

    downloaded_count += 1
    print(f'下载: {save_name}')

    mail.logout()

    SetVar('下载简历数', downloaded_count)
    print(f'简历采集完成,共下载{downloaded_count}份')

    招聘平台页面直接采集(备选方案)

    有些HR习惯直接在招聘平台页面上下载简历。各平台的简历列表页面结构:

    拼多多店群自动化报活动上架!

    # Boss直聘 – 沟通中的人才列表
    //div[contains(@class,'chat-record-item')] # 候选人卡片
    .//span[contains(@class,'name')] # 候选人姓名
    .//span[contains(@class,'job-name')] # 应聘职位
    .//a[contains(text(),'查看简历')] # 简历链接

    # 前程无忧 – 收到的简历列表
    //div[contains(@class,'resume-item')] # 简历行
    .//span[contains(@class,'name-text')] # 姓名
    .//a[contains(@class,'download')] # 下载按钮

    # 智联招聘 – 应聘简历列表
    //div[contains(@class,'apply-item')] # 应聘记录行


    第二步:简历信息解析

    下载简历PDF后,需要提取关键信息。这块用影刀内置OCR或者Python的PDF解析库来处理。

    # 影刀Python步骤:简历PDF解析与关键信息提取
    # 依赖:pip install PyPDF2 pdfplumber

    import PyPDF2
    import pdfplumber
    import re
    import json
    import os

    resume_dir = GetVar('简历存储目录')
    results = []

    # 遍历下载的简历PDF
    for filename in os.listdir(resume_dir):
    if not filename.endswith('.pdf'):
    continue

    filepath = os.path.join(resume_dir, filename)
    full_text = ''

    # 方法1:先用pdfplumber提取(对表格格式更好)
    try:
    with pdfplumber.open(filepath) as pdf:
    for page in pdf.pages:
    page_text = page.extract_text()
    if page_text:
    full_text += page_text + '\\n'
    except:
    pass

    # 方法2:如果pdfplumber没提取到文本,用PyPDF2
    if not full_text.strip():
    try:
    with open(filepath, 'rb') as f:
    reader = PyPDF2.PdfReader(f)
    for page in reader.pages:
    full_text += page.extract_text() + '\\n'
    except:
    pass

    # 方法3:如果还是空的,用影刀的OCR指令单独处理
    if not full_text.strip():
    print(f'文本提取失败,建议用OCR处理: {filename}')
    continue

    # ========== 关键信息提取 ==========

    # 1. 提取姓名(通常在简历开头,2-4个中文字符)
    # 简历第一行经常是姓名,取前几行中符合规则的
    lines = full_text.strip().split('\\n')
    name = ''
    for line in lines[:5]:
    line = line.strip()
    # 匹配2-4个中文字符,且不包含常见非姓名关键词
    if re.match(r'^[\\u4e00-\\u9fa5]{2,4}$', line):
    if not any(kw in line for kw in ['简历', '个人', '联系', '男', '女', '应聘']):
    name = line
    break

    # 如果第一行没提取到,尝试用"姓名"关键词定位
    if not name:
    name_match = re.search(r'姓名[::\\s]*([\\u4e00-\\u9fa5]{2,4})', full_text)
    name = name_match.group(1) if name_match else ''

    # 2. 提取手机号
    phone = ''
    phone_match = re.search(r'1[3-9]\\d{9}', full_text)
    phone = phone_match.group() if phone_match else ''

    # 3. 提取邮箱
    email_addr = ''
    email_match = re.search(r'[\\w.+-]+@[\\w-]+\\.[\\w.]+', full_text)
    email_addr = email_match.group() if email_match else ''

    # 4. 提取学历
    education = ''
    edu_patterns = ['博士', '硕士', '本科', '大专', '中专', '高中']
    for level in edu_patterns:
    if level in full_text:
    education = level
    # 尝试提取学校名称(学历关键词前后20字范围内的学校相关词)
    edu_pos = full_text.find(level)
    nearby = full_text[max(0, edu_pos–30):edu_pos+30]
    school_match = re.search(r'([\\u4e00-\\u9fa5]{2,10}(大学|学院|学校))', nearby)
    if school_match:
    education = f'{school_match.group(1)} {level}'
    break

    # 5. 提取工作年限
    experience = ''
    exp_match = re.search(r'(\\d+)[\\s-]*年.*?经验', full_text)
    if exp_match:
    experience = f'{exp_match.group(1)}年'
    else:
    # 或者从工作经历的时间跨度推算
    year_ranges = re.findall(r'(\\d{4})\\s*[.\\-/至到]\\s*(\\d{4}|至今|今)', full_text)
    if year_ranges:
    start_year = min(int(y[0]) for y in year_ranges)
    total_years = 2026 – start_year # 当前年份
    experience = f'约{total_years}年'

    # 6. 提取期望薪资
    expected_salary = ''
    salary_match = re.search(r'(期望|意向|薪资要求|薪酬).*?(\\d+)[kK千]?\\s*[-~至]\\s*(\\d+)[kK千]?', full_text)
    if salary_match:
    expected_salary = f'{salary_match.group(2)}K-{salary_match.group(3)}K'
    else:
    # 只提取单一数字
    salary_single = re.search(r'(期望|意向).*?(\\d+)[kK千]', full_text)
    if salary_single:
    expected_salary = f'{salary_single.group(2)}K'

    # 7. 提取应聘职位
    position = ''
    position_match = re.search(r'(求职意向|应聘|意向岗位|期望职位)[::\\s]*([\\u4e00-\\u9fa5a-zA-Z+/]{2,20})', full_text)
    position = position_match.group(2) if position_match else filename.split('_')[1] if '_' in filename else ''

    results.append({
    '姓名': name,
    '手机': phone,
    '邮箱': email_addr,
    '学历': education,
    '工作经验': experience,
    '期望薪资': expected_salary,
    '应聘职位': position,
    '简历来源': filename,
    '简历路径': filepath,
    '解析时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
    '面试状态': '待筛选',
    '评分': ''
    })

    SetVar('简历解析结果', json.dumps(results, ensure_ascii=False))
    SetVar('解析简历数', len(results))
    print(f'简历解析完成,共{len(results)}份')
    for r in results:
    print(f' {r["姓名"]} | {r["学历"]} | {r["工作经验"]} | {r["期望薪资"]} | {r["应聘职位"]}')


    第三步:写入飞书招聘管理表

    将解析结果写入飞书多维表格,HR可以在表格中直接进行筛选、打分、安排面试。

    飞书Base招聘管理表字段设计:

    字段类型说明
    候选人姓名 文本 自动提取
    手机号 文本 自动提取
    邮箱 文本 自动提取
    学历 单选 博士/硕士/本科/大专/其他
    工作经验 文本 如:3年
    期望薪资 文本 如:15K-20K
    应聘职位 单选 按职位预设选项
    简历附件 附件 上传简历PDF
    面试状态 单选 待筛选/已邀约/一面/二面/已通过/已拒绝
    面试时间 日期时间 安排的面试时间
    HR评分 数字 1-5分
    备注 多行文本 HR手动填写

    第四步:面试自动安排

    筛选出合适的候选人后,自动发送面试邀请邮件并创建飞书日程。

    在这里插入图片描述

    # 影刀Python步骤:发送面试邀请邮件 + 创建飞书日程

    import smtplib
    from email.mime.text import MIMEText
    from email.mime.multipart import MIMEMultipart
    import json
    import requests
    from datetime import datetime, timedelta

    # ========== 邮件配置 ==========
    SMTP_SERVER = GetVar('SMTP服务器') # 如: smtp.163.com
    SMTP_PORT = int(GetVar('SMTP端口')) # 如: 465 (SSL)
    EMAIL_ADDRESS = GetVar('发送邮箱')
    EMAIL_PASSWORD = GetVar('邮箱授权码')

    # ========== 候选人数据 ==========
    candidates = json.loads(GetVar('待发邀请候选人'))
    interview_date = GetVar('面试日期') # 如: 2024-07-15
    interview_time = GetVar('面试时间') # 如: 14:00
    interview_location = GetVar('面试地点') # 或线上会议链接

    for candidate in candidates:
    # === 发送面试邀请邮件 ===
    msg = MIMEMultipart()
    msg['From'] = EMAIL_ADDRESS
    msg['To'] = candidate['邮箱']
    msg['Subject'] = f'面试邀请 – {candidate["应聘职位"]} – {candidate["姓名"]}'

    # 邮件正文
    body = f"""{candidate['姓名']},您好!

    感谢您投递{candidate['应聘职位']}职位,经过简历筛选,我们诚挚邀请您参加面试。

    面试时间:{interview_date} {interview_time}
    面试方式:
    {'线下面试,地址:' + interview_location if interview_location else '线上面试,会议链接将在面试前发送'}
    预计时长:约30-60分钟

    请回复本邮件确认是否参加,如有时间冲突可沟通调整。

    期待与您的交流!

    —
    此邮件由RPA自动发送,请勿回复。如有疑问请联系HR。
    """
    msg.attach(MIMEText(body, 'plain', 'utf-8'))

    try:
    server = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT)
    server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
    server.sendmail(EMAIL_ADDRESS, candidate['邮箱'], msg.as_string())
    server.quit()
    print(f'面试邀请已发送: {candidate["姓名"]} ({candidate["邮箱"]})')

    # 更新状态
    candidate['面试状态'] = '已邀约'
    candidate['面试时间'] = f'{interview_date} {interview_time}'
    except Exception as e:
    print(f'发送失败: {candidate["姓名"]}: {e}')
    candidate['面试状态'] = '发送失败'

    SetVar('邀请发送结果', json.dumps(candidates, ensure_ascii=False))


    第五步:入职资料收集自动化

    面试通过后,需要收集候选人的入职资料(身份证、学历证书、离职证明等)。

    资料清单自动推送模板:

    入职资料清单:
    □ 身份证正反面复印件
    □ 学历/学位证书复印件
    □ 离职证明原件
    □ 银行卡信息(工资卡)
    □ 一寸照片电子版
    □ 体检报告
    □ 入职登记表(已附在邮件中)

    请在{截止日期}前将所有电子版发送至HR邮箱,纸质版可入职当天携带。


    在这里插入图片描述

    完整流程编排

    定时任务(每日8:00、14:00各执行一次)
    │
    ├─→ 步骤1:采集新简历
    │ ├─ 登录招聘平台下载最新简历
    │ └─ 检查邮箱,下载新到的简历附件
    │
    ├─→ 步骤2:简历解析
    │ ├─ 逐份解析PDF关键信息
    │ └─ 写入飞书招聘管理表
    │
    ├─→ 步骤3:自动初筛(可选)
    │ ├─ 学历不满足条件 → 自动标记"不合适"
    │ ├─ 工作经验不足 → 自动标记"不合适"
    │ └─ 合适 → 标记"待筛选",提醒HR查看
    │
    ├─→ 步骤4:HR手动筛选(人工操作)
    │ └─ HR在飞书表中查看并打分
    │
    ├─→ 步骤5:发送面试邀请
    │ ├─ 对"已通过筛选"的候选人
    │ ├─ 自动发送面试邀请邮件
    │ └─ 自动创建飞书面试日历
    │
    ├─→ 步骤6:面试前提醒(定时任务)
    │ ├─ 面试前一天 → 发送提醒邮件给候选人
    │ └─ 面试当天 → 飞书消息提醒面试官
    │
    └─→ 步骤7:入职资料收集
    ├─ 面试通过后自动发送资料清单
    ├─ 定期检查是否收齐
    └─ 资料不全时自动催办


    常见问题速查

    问题1:PDF简历文本提取不出来(全是空白)

    现象:pdfplumber和PyPDF2都提取不到文字。 原因:有些简历是扫描版的(图片格式),或者用了特殊字体编码。 解决方式:

    • 用影刀的OCR指令提取文本(设置识别语言为中文)
    • 或者用百度OCR的PDF识别API:# 百度OCR处理扫描版PDF
      from aip import AipOcr
      ![在这里插入图片描述](https://i–blog.csdnimg.cn/direct/f58277ccf1d7467ca15f189367fe51e9.png#pic_center)

      client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
      result = client.pdf_ocr(pdf_path)

    问题2:候选人姓名解析错误(比如把"联系方式"识别为名字)

    现象:解析结果中的姓名栏显示的是"联系方式"、"个人简历"等无关文字。 原因:PDF提取文本的前几行可能包含非姓名内容。 解决方式:增加姓名验证规则——匹配到的文本必须全是中文字符,长度2-4个,且不在排除词列表中:

    exclude_names = ['简历', '个人', '联系', '求职', '应聘', '自我', '在线', '联系方式']

    问题3:Boss直聘等平台的简历没有直接的下载按钮

    TEMU店群矩阵自动化运营核价报活动

    现象:Boss直聘的简历需要"查看"而不是下载,无法直接获取PDF。 原因:部分平台为了保护候选人隐私,简历是分片展示的。 解决方式:

    • 用影刀的"网页截图"截取完整简历页面,保存为PDF
    • 或者手动一个个浏览,采集页面上的文本信息(不推荐,效率低)
    • 另一个方案:在Boss直聘上引导候选人将简历发送到指定邮箱

    问题4:发送面试通知邮件被判定为垃圾邮件

    在这里插入图片描述

    现象:发出的面试邀请邮件都被邮箱系统归类到垃圾箱。 原因:短时间内大量发送相似内容的邮件,触发反垃圾机制。 解决方式:

    • 每封邮件之间间隔5-10秒
    • 不要使用纯HTML格式,使用纯文本格式更具个人化感觉
    • 重要候选人手动发送,自动化仅处理初级筛选

    问题5:入职资料追了半天,候选人说"没收到"

    现象:发了资料清单邮件,候选人说没收到,结果资料交得晚。 原因:邮件可能进垃圾箱,或者候选人没及时查看。 解决方式:

    • 邮件 + 短信双通道通知(短信可通过阿里云短信服务API发送)
    • 在飞书Base中跟踪资料收集进度,逾期自动发送催办消息
    • 加入"已读回执"功能(技术上有局限,不做强制要求)

    问题6:不同招聘平台的简历格式差异太大

    现象:Boss直聘导出的PDF和前程无忧导出的PDF结构完全不同,提取规则很难统一。 原因:各平台简历模板不同。 在这里插入图片描述

    解决方式:

    • 不要试图用一套规则覆盖所有平台,按平台分表处理
    • 把简历文件名中加入平台标识(如Boss直聘_姓名.pdf)
    • 建立平台→字段映射配置表,每个平台单独维护提取规则

    推荐资源

    • Python PDF解析:PyPDF2 / pdfplumber / reportlab
    • 百度OCR PDF识别:https://cloud.baidu.com/product/ocr
    • 飞书日历API:https://open.feishu.cn/document/server-docs/calendar-v4/calendar/introduction
    • 邮箱IMAP服务开启指南(网易/QQ/企业微信邮箱帮助中心)

    内容标签

    #影刀RPA #HR自动化 #简历筛选 #招聘自动化 #入职流程 #飞书 #OCR #Python

    在这里插入图片描述


    作者:林焱 | 影刀RPA深度使用者,两年以上实操经验 | 专注于企业办公自动化,涵盖HR、财务、行政等领域 在这里插入图片描述

    赞(0)
    未经允许不得转载:171主机测评 » 影刀RPA实操指南:HR场景简历自动筛选与入职流程自动化
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址