原文: How to Build a Résumé Screening System Using Python and Multiprocessing
招聘合适的人选,往往从一项耗时的工作开始:筛选简历。如果你发布过职位招聘,一定体会过收件箱里有数百份申请,而你得花数小时手动审阅每份简历的烦恼。
本文将带你用纯 Python 搭建一个简历筛选系统,重点讲解核心编程概念和多进程的运用。你会创建一个自定义系统,通过将非结构化的简历文档转化为排名榜单,实现评估流程的自动化。
阅读完本指南后,你将能够:
- 解析文档:使用 Python 从 PDF 和 DOCX 简历中提取文本
- 提取信息:从简历内容中识别技能与关键词
- 设计评分算法:用加权逻辑客观地为候选人排序
- 构建 Web 界面:使用 Streamlit 完成
- 部署应用:在 Streamlit Cloud 上部署应用,供公众访问
按照本教程操作,你将构建一个能在几秒内处理数百份简历的工具。
源代码见 GitHub 仓库
目录
- 前置要求
- 项目概览
- 系统如何工作
- 系统架构
- 项目结构
- 步骤 1:搭建项目
- 步骤 2:构建简历解析器
- 步骤 3:构建关键词提取器
- 步骤 4:实现评分引擎
- 步骤 5:构建 Web 界面
- 步骤 6:测试系统
- 步骤 7:部署应用
- 总结
前置要求
要学习本教程,你需要具备:
- Python 基础知识(函数、循环、字典)
- 已安装 Python 3.8 或更高版本
- 会用
pip安装包 - 代码编辑器(如 VS Code、PyCharm 或任意你喜欢的编辑器)
项目概览
本指南将开发一个系统:输入一个简历文件夹和一份职位描述(JD),系统会处理每份简历、提取相关信息,并根据候选人与职位要求的匹配程度计算得分。
系统如何工作
项目包含四个核心组件:
- 简历解析器:读取 PDF 和 DOCX 文件并提取文本
- 职位描述解析器:分析职位描述以识别所需技能
- 关键词提取器:将简历内容与技能分类体系进行匹配
- 评分引擎:使用加权算法对候选人排序
评分公式
使用的评分公式如下:
总分 =
(必备技能 × 50%)+
(优先技能 × 25%)+
(经验 × 15%)+
(关键词 × 10%)
这样设计可以确保核心技能比次要关键词权重更高。
这种方法如何有助于减少偏见
本系统基于预定义标准评估简历,而不是主观判断。每份简历都根据同一套必备技能、优先技能、经验指标和关键词进行打分。
由于所有候选人都使用同一套加权公式评估,写作风格、排版或个人偏好等主观因素不会影响排名。评分逻辑只关注简历与职位要求的匹配程度。
通过将评估过程标准化,系统促进了更一致、更客观的筛选,有助于在简历初筛阶段减少偏见。
系统架构
输入 处理 输出
───── ────────── ─────
简历 ──► 简历解析器 ──► 关键词提取器 ──┐
(PDF/DOCX) │
├──► 评分引擎 ──► 排名结果
职位描述 ──► 职位描述解析器 ────────────┘
(TXT/PDF)
系统遵循简单的“输入—处理—输出”流程。
简历和职位描述作为输入。简历解析器从每份简历中提取文本,职位描述解析器从职位描述中识别必备技能和优先技能。
提取出的简历文本随后传给关键词提取器,该模块根据预定义的技能分类体系匹配技能和关键词。
最后,评分引擎应用加权公式为每位候选人计算得分,并输出一份按分数排序的简历列表。
项目结构
resume_screening_system/
├── app.py # Streamlit Web 界面
├── main.py # 命令行界面
├── parsers/
│ ├── resume_parser.py # PDF/DOCX 文本提取
│ └── jd_parser.py # 职位描述解析
├── extractors/
│ └── keyword_extractor.py # 技能与经验提取
├── matcher/
│ └── scorer.py # 评分算法
├── data/
│ ├── config.json # 评分权重配置
│ └── skills_taxonomy.json # 技能数据库
└── requirements.txt # 依赖
项目按清晰的模块化目录组织。解析逻辑、关键词提取和评分分别放在各自文件夹中,配置文件与数据单独存放,便于浏览、维护和扩展。
步骤 1:搭建项目
创建目录结构并设置虚拟环境:
mkdir resume_screening_system
cd resume_screening_system
mkdir parsers extractors matcher data input output
python -m venv venv
然后激活虚拟环境:
# Windows
source venv/Scripts/activate
# macOS / Linux
source venv/bin/activate
安装所需依赖:
pip install PyPDF2 python-docx streamlit pandas
步骤 2:构建简历解析器
简历解析器针对不同文件格式使用不同的提取方法。
对于 PDF,解析器逐页打开文档,用 PDF 阅读器从每页提取文本,再合并成单个字符串供后续处理。
对于 DOCX,解析器读取文档中的每个段落,将段落文本拼接成一块。这样无论简历格式如何,都能得到一致的文本输出。
将简历统一转为纯文本后,关键词提取和评分等组件就能高效工作。
文件: parsers/resume_parser.py
def _extract_pdf(self, file_path: Path) -> str:
text = ""
with open(file_path, "rb") as file:
pdf_reader = PyPDF2.PdfReader(file)
for page in pdf_reader.pages:
page_text = page.extract_text()
if page_text:
text += page_text + "\n"
return text.strip()
def _extract_docx(self, file_path: Path) -> str:
from docx import Document
doc = Document(file_path)
return "\n".join(
para.text for para in doc.paragraphs
).strip()
步骤 3:构建关键词提取器
本项目使用 Kaggle 上的简历数据集,确保逻辑在真实职业数据上可用。关键词提取器通过扫描简历文本来识别技能。
简历文本先转为小写,以便不区分大小写地匹配。预定义的技能分类体系存储每个技能及其可能变体,提取器用这些变体与简历文本比对。
匹配时使用词边界,避免部分匹配(例如在 “JavaScript” 里匹配到 “Java”)。匹配到的技能存入集合以避免重复。
这种方式能在所有简历上实现一致、可控的技能识别。
文件: extractors/keyword_extractor.py
def extract_skills(self, text: str) -> Set[str]:
text_lower = text.lower()
found_skills = set()
for category, skills_dict in self.skills_taxonomy.items():
for skill_name, variations in skills_dict.items():
for variation in variations:
# 防止 "Java" 匹配到 "JavaScript"
pattern = r"\b" + re.escape(variation) + r"\b"
if re.search(pattern, text_lower):
found_skills.add(skill_name)
break
return found_skills
步骤 4:实现评分引擎
为得到客观排名,系统使用加权评分公式。
| 组件 | 权重 | 说明 |
|---|---|---|
| 必备技能 | 50% | 核心技术需求 |
| 优先技能 | 25% | 差异化竞争力 |
| 经验 | 15% | 专业深度 |
| 关键词 | 10% | 领域熟悉度 |
总分 =
(S_req × 0.50) +
(S_pref × 0.25) +
(E_exp × 0.15) +
(K_key × 0.10)
评分引擎用上述权重为每份简历计算最终得分。
它统计简历中出现的必备技能、优先技能、经验指标和关键词数量,每个数量乘以其对应权重(必备技能权重最高),加权值相加得到单一分数,再按该分数对简历排序,生成候选人排名列表。
步骤 5:构建 Web 界面
Streamlit 为简历筛选系统提供了简单的 Web 界面。
文本区域用于输入职位描述,文件上传器用于上传多份简历。点击按钮后,Streamlit 触发后端逻辑解析简历、提取数据并计算得分,结果在浏览器中展示,用户无需使用命令行即可完成筛选。
文件: app.py
import streamlit as st
jd_text = st.text_area(
"在此粘贴职位描述:",
height=300
)
uploaded_files = st.file_uploader(
"上传简历文件:",
type=["pdf", "docx", "txt"],
accept_multiple_files=True
)
if st.button("筛选简历", type="primary"):
st.success("正在处理简历...")
运行应用:
streamlit run app.py
应用将运行在 http://localhost:8500。
步骤 6:测试系统
示例职位描述输入
下面是一份可用于测试的示例职位描述:
我们正在寻找一名具有扎实后端开发经验的高级 Python 开发工程师。
必备技能:
- Python
- Django
- REST API
- SQL
优先技能:
- PostgreSQL
- Docker
- AWS
经验要求:
- 3 年以上 Python 专业开发经验
- 有构建 Web 应用的经验
该输入帮助系统识别必备技能、优先技能和经验关键词,供评分引擎对简历排序。
python main.py
示例输出
============================================================
筛选结果
============================================================
第 1 名:Alice Johnson | 得分:85.42/100 | 匹配:python、django、postgresql
第 2 名:Carol Davis | 得分:72.50/100 | 匹配:python、django
步骤 7:部署应用
若要让系统对外可访问:
- 将代码推送到 GitHub
- 打开 share.streamlit.io
- 选择你的
app.py文件 - 部署应用
应用将发布在:
https://your-app-name.streamlit.app
总结
在本教程中,你使用 Python 从零搭建了一个完整的简历筛选系统。通过结合文本处理、结构化评分和自动化,该项目展示了如何将手动简历筛选转变为高效、客观的流程。
该系统有助于减少偏见、节省时间,并更一致地评估候选人。Happy coding!