通用岗位简历批量筛选工具。输入任意岗位JD和候选人简历文件夹,自动解析JD提取评估维度,对多候选人进行统一打分排序,输出标准化筛选报告。
批量解析多个候选人的简历,对照岗位JD进行多维度打分,输出:
text
┌─────────────────────────────────────────────────────────────┐
│ 步骤1:解析JD │
│ ↓ │
│ • 提取硬性要求(学历/年限/专业/证书等) │
│ • 提取评估维度(3-5个核心能力项) │
│ • 提取加分项(专利/证书/特定经验等) │
│ ↓ │
│ 步骤2:解析简历 │
│ ↓ │
│ • 提取基本信息(姓名/学历/工作年限) │
│ • 提取工作经历(公司/职位/时间/业绩) │
│ • 提取技能/项目/证书等信息 │
│ ↓ │
│ 步骤3:多维度打分 │
│ ↓ │
│ • 基础维度打分(6项通用维度) │
│ • JD专项维度打分(根据JD自动生成) │
│ ↓ │
│ 步骤4:排序输出 │
│ ↓ │
│ • 生成筛选报告.xlsx │
│ • 生成面试邀请名单.xlsx │
└─────────────────────────────────────────────────────────────┘
总分:100分制 - 所有候选人按同一标准评分,确保跨岗位可比性。
维度分值评分标准学历15分博士15/硕士12/本科8/大专4工作年限10分8年+满分10/5年+8分/3年+6分/1年+4分技能匹配25分与岗位核心技能关键词匹配度,按匹配数量计算项目/经验质量25分目标岗位相关项目经验质量,分4个等级职业稳定性15分8年+15分/5年+12分/3年+8分/1年+5分软性能力10分沟通协作、团队配合等,默认8分
python
def calc_skill_match(skills, job_type):
"""计算技能匹配得分"""
all_text = " ".join(skills).lower()
if job_type == "tech":
# 技术岗核心技能
tech_skills = ["CUDA", "OpenCL", "SIMT", "SIMD", "GPGPU", "GPU", "NPU", "RISC-V",
"Verilog", "VHDL", "UVM", "RTL", "Gem5", "GPGPU-Sim", "SystemC",
"SoC", "FPGA", "芯片架构", "微架构", "指令集", "AI", "深度学习", "流片", "量产"]
matched = [s for s in tech_skills if s.lower() in all_text]
return min(25, len(matched) * 3 + (5 if len(matched) >= 5 else 0))
elif job_type == "market":
# 市场岗核心技能
market_skills = ["市场开拓", "客户关系", "项目管理", "PMP", "AEC-Q", "ISO26262", "车规", "上车", "Tier1", "整车"]
matched = [s for s in market_skills if s.lower() in all_text]
return min(25, len(matched) * 4 + (5 if len(matched) >= 4 else 0))
return 15 # 默认
等级技术岗分值市场岗分值条件卓越级22-25分22-25分有目标岗位同类产品主导经验,成果可量化良好级16-21分16-21分有目标岗位同类项目完整参与经验中等级10-15分10-15分有相近岗位项目经验基础级5-9分5-9分有相关基础经验,无直接项目经历
分数区间建议≥85分✅ 强烈推荐70-84分✅ 推荐60-69分⚠️ 备选<60分❌ 不推荐
门槛项要求不满足处理学历JD要求的最低学历直接淘汰或总分上限60分工作年限JD要求的最少年限明显不足者直接淘汰必备技能JD要求的核心技能无必备技能者直接淘汰行业经验JD要求的特定行业无行业经验者降一档
python
def parse_jd(jd_content):
"""从JD内容中自动提取评估维度"""
# 1. 提取硬性要求
hard_requirements = {
'学历': extract_education(jd_content), # 如:硕士及以上
'年限': extract_experience(jd_content), # 如:5年+
'专业': extract_major(jd_content), # 如:计算机相关
}
# 2. 提取评估维度(3-5个核心能力)
evaluation_dimensions = extract_core_abilities(jd_content)
# 如:[架构设计, 算法开发, 团队管理, 客户对接]
# 3. 提取加分项
bonus_items = extract_bonus_items(jd_content)
# 如:[PMP认证, CPA, 行业排名前十公司经验]
return hard_requirements, evaluation_dimensions, bonus_items
类别识别关键词学历要求"硕士及以上"、"本科985/211"、"全日制"年限要求"5年+"、"8年+"、"10年以上"硬性技能"熟练掌握"、"精通"、"必须具备"加分技能"加分"、"优先"、"更佳"行业经验"医疗行业"、"金融行业"、"汽车电子"证书资质"CFA"、"CPA"、"PMP"、"司法考试"
岗位类型权重调整策略技术/研发类技能匹配度25-30分,项目经验质量25-30分算法/AI类技能匹配度30-40分,学历权重提高(15-18分)管理类软性能力15-20分,工作年限权重提高市场/销售类行业经验权重提高,技能匹配度权重降低运营/产品类项目经验权重提高,学历权重降低至8-10分职能/支持类稳定性权重提高,技能匹配度权重降低
根据JD提取的核心能力进行评估:
等级分值条件极强18-20分同时满足岗位JD要求的全部核心能力项强14-17分满足岗位JD要求的3项以上核心能力中9-13分满足岗位JD要求的2项核心能力弱4-8分满足岗位JD要求的1项核心能力极弱0-3分无相关经验 → 淘汰或降级
等级分值条件卓越级23-25分有目标岗位同类产品/项目主导经验,成果可量化良好级18-22分有目标岗位同类项目完整参与经验中等级12-17分有相近岗位项目经验基础级6-11分有相关基础经验,但无直接项目经历无关级0-5分无目标岗位直接经验 → 降级处理
注:卓越级指主导并产生明确成果的项目,良好级指完整参与但非主导,中等级指行业相近但岗位不同
建议等级分数区间建议动作强烈推荐≥80分优先安排面试(核心岗位/稀缺人才)推荐70-79分安排面试(匹配度良好)备选60-69分根据招聘数量决定(基本匹配)不推荐<60分不进入面试(存在明显短板)
注:分数区间可根据岗位紧急程度调整,如急招岗位可将"备选"区间提升至55-59分
python
import pdfplumber # PDF文本提取
from docx import Document # Word文档解析
import re # 正则表达式
from pathlib import Path
python
def read_pdf(path):
text = ""
with pdfplumber.open(path) as pdf:
for page in pdf.pages:
text += page.extract_text() or ""
return text
python
def read_docx(path):
doc = Document(path)
return "\n".join([p.text for p in doc.paragraphs])
python
def extract_name(content, filename):
"""提取简历姓名,兼容多种格式"""
# 1. 优先匹配 "姓 名:冯亮" 格式(中间有空格/制表符)
name_match = re.search(r'姓\s*名[::]\s*([\u4e00-\u9fa5]{2,4})', content)
if name_match:
return name_match.group(1)
# 2. 备用:从文件名获取(当简历正文无标准姓名格式时)
return filename.replace('.docx', '').replace('.pdf', '').strip()
python
def extract_work_years(content):
"""提取工作年限"""
# 优先匹配 "工作年限:9年" 格式
year_match = re.search(r"工作年限[::]\s*(\d+)", content)
if year_match:
return int(year_match.group(1))
# 备用:从工作经历时间范围推算(取最早年份)
dates = re.findall(r"(\d{4})[.\-/~]", content)
if dates:
try:
years = [int(d) for d in dates if len(d) == 4]
if years:
return 2026 - min(years)
except:
pass
return 5 # 默认值
python
def extract_education(content):
"""提取学历层次"""
if "博士" in content:
return "博士"
elif "硕士" in content or "研究生" in content:
return "硕士"
elif "本科" in content:
return "本科"
else:
return "大专"
python
def extract_skills(content):
"""提取核心技能关键词"""
skills = []
content_lower = content.lower()
skill_pool = [
"CUDA", "OpenCL", "ROCm", "SIMT", "SIMD", "GPGPU", "GPU", "NPU", "TPU", "RISC-V",
"Verilog", "VHDL", "SystemVerilog", "UVM", "RTL",
"Gem5", "GPGPU-Sim", "SystemC",
"SoC", "FPGA", "ASIC",
"Linux", "KVM", "虚拟化",
"AEC-Q", "ISO26262", "车规",
"芯片架构", "微架构", "指令集", "ISA",
"AI", "人工智能", "深度学习", "机器学习",
"市场开拓", "客户关系", "渠道管理", "项目管理", "PMP",
"流片", "量产", "EDA",
"物理", "电路", "半导体", "器件",
]
for skill in skill_pool:
if skill.lower() in content_lower:
skills.append(skill)
return list(set(skills))
python
def extract_companies(content):
"""提取工作单位"""
companies = re.findall(r'([\u4e00-\u9fa5]{2,15}(?:公司|集团|科技|技术|有限|股份|研究所))', content)
return list(set(companies))[:5]
Sheet1: 筛选结果汇总(全部候选人)
序号姓名应聘岗位综合得分排名学历工作年限技能匹配项目经验稳定性软性邀请状态核心技能
数据要求:
Sheet2-N: 各岗位筛选结果(含评分依据)
每个岗位一个Sheet,Sheet命名=岗位名称(最长20字符)
包含两部分内容:
第一部分:候选人得分汇总表
| 序号 | 姓名 | 综合得分 | 排名 | 学历 | 工作年限 | 技能匹配 | 项目经验 | 稳定性 | 软性 | 邀请状态 | |:---:|:---|:---:|:---:|:---|:---:|:---:|:---:|:---:|:---:|:---:|:---|
第二部分:候选人详细评分依据(每人占用约15行)
每位候选人包含以下评分明细:
text
【候选人:XXX】
■ 学历评分(满分15分,得X分)
评价依据:[学历层次],[院校背景](如适用)
结论:满足/不满足JD学历要求
■ 工作年限评分(满分10分,得X分)
评价依据:工作年限X年,对应档位[X年+],得X分
结论:满足/不满足JD年限要求
■ 技能匹配评分(满分25分,得X分)
匹配技能:[列出所有匹配的技能关键词,用"/"分隔]
计算方法:匹配X个技能 × 3分 = X分(上限25分)
结论:技能匹配度[X/高/中/低]
■ 项目经验评分(满分25分,得X分)
评价依据:[简要描述项目经验质量]
等级认定:[卓越/良好/中等/基础级]
结论:项目经验与岗位要求[匹配度高/中/低]
■ 职业稳定性评分(满分15分,得X分)
评价依据:工作年限X年,平均每段工作时间约X年
结论:职业稳定性[高/中/低]
■ 软性能力评分(满分10分,得X分)
评价依据:[从简历中提取的软性能力描述]
结论:软性能力[强/中/弱](默认8分)
■ 综合评价
总分:X分(学历X+年限X+技能X+项目X+稳定X+软性X)
建议:✅强烈推荐/✅推荐/⚠️备选/❌不推荐
■ 核心优势
1. [优势1]
2. [优势2]
■ 风险点
1. [风险点1]
2. [风险点2]
■ 面试关注要点
1. [关注点1]
2. [关注点2]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Sheet1: 邀请名单
序号姓名综合得分学历工作年限核心优势邀请状态面试时间面试形式主面试官备注
Sheet2: 候选人关键信息
每个候选人一个区块:
text
【候选人:姓名】
综合得分:XX分 排名:第X名
关键经历:━━━━━━━━━━━━━━━━━━━━
核心技能:━━━━━━━━━━━━━━━━━━━━
风险提示:━━━━━━━━━━━━━━━━━━━━
面试关注点:━━━━━━━━━━━━━━━━━━
Sheet1: 评分维度总览
维度最高分评分说明学历15分按院校层次打分工作年限10分按年限档位打分技能匹配度20分按与JD要求匹配度打分项目经验质量25分按项目规模/成果分级职业稳定性10分按平均每段工作时间打分软性能力10分按管理/协作/沟通打分JD专项加分10分根据具体岗位JD提取
Sheet2: 筛选标准
分数区间建议≥80分✅ 强烈推荐70-79分✅ 推荐60-69分⚠️ 备选<60分❌ 不推荐
Sheet3: 学历评分细则
学历层次分值博士(985/211)15分硕士(985/211)13分硕士(普通院校)11分本科(985/211)8分本科(普通院校)6分大专3分
Sheet4: 各项评分细则 详细列出其他维度的评分标准
Sheet1: 全部候选人汇总
候选人学历年限技能匹配项目质量稳定性软性JD专项总分排名建议
Sheet2-N: 各候选人详细评分说明
维度得分评分依据(每行一个维度的详细评分说明)核心优势:xxx风险点:xxx
Excel格式要求:
文件命名: {岗位名称}-筛选报告-{日期}.xlsx
权限问题处理:WSL环境下直接写入/mnt/d/路径可能遇到PermissionError
python
# 解决方案:先写入/tmp,再复制到目标目录
import shutil
output_path = '/tmp/简历筛选报告.xlsx'
wb.save(output_path)
# 复制到Downloads目录
shutil.copy(output_path, '/mnt/c/Users/{用户名}/Downloads/')
当用户要求重新生成筛选报告时,必须遵循以下步骤避免数据不一致:
bash
# 删除该目录下所有之前生成的筛选报告文件
rm -f /目标目录/简历筛选报告*.xlsx
rm -f /目标目录/面试邀请名单*.xlsx
rm -f /目标目录/候选人详细评分依据*.xlsx
❌ 先生成文件A发现问题后修改评分再生成文件B ❌ 筛选结果汇总和面试邀请名单使用不同的评分结果 ❌ 保留旧的Excel文件只覆盖部分sheet
✅ 确认评分标准 → 删除旧文件 → 生成新文件 → 验证一致性