输入PDF简历,自动提取姓名、电话、邮箱、工作经历等字段,导出Excel表格。HR再也不用手动复制粘贴。
你有没有试过手动把几十份PDF简历里的信息一个个敲进Excel?手指敲到酸,眼睛看到花,还老容易出错。
我上周帮朋友的公司整理秋招简历,两百多份PDF,她花了整整三天才录完。她说要是早有人做个自动化工具,能省出半个月时间。
这就是我要做的——一个PDF简历智能解析器。只要扔进去PDF文件,它就能自动识别关键信息,直接导出整齐的Excel表。不用懂复杂的OCR,纯文本PDF也能搞定。
项目背景
招聘旺季,HR面临的最大痛点之一就是简历处理效率低。PDF格式的简历虽然在排版上好看,但信息提取极其麻烦。尤其是很多简历是扫描件或者混合了图片和文字的PDF,传统方法很难批量处理。
这个项目适合以下场景:
- HR初筛阶段快速提取候选人基本信息
- 猎头整理候选人资料库
- 个人求职者管理自己的申请记录
目标是:输入一个或多个PDF简历文件,输出包含姓名、电话、邮箱、教育经历、工作经历的结构化Excel文件。
技术选型
| 组件 | 选型 | 理由 |
|---|---|---|
| 语言 | Python 3.9+ | 生态丰富,开发速度快 |
| PDF解析 | pdfplumber / pypdf | 支持文本提取,对中文友好 |
| 数据处理 | pandas | DataFrame操作方便 |
| Excel输出 | openpyxl | 格式控制灵活 |
| AI增强(可选) | OpenAI API | 用于模糊字段的语义理解 |
| 批量处理 | argparse / pathlib | 支持文件夹批量扫描 |
不需要数据库。所有数据在内存中处理后直接写入Excel。
实现步骤
第一步:安装依赖
pip install pdfplumber pandas openpyxl python-dotenv
就三个核心包。pdfplumber负责解析PDF,pandas处理表格数据,openpyxl写Excel文件。
第二步:创建项目目录结构
mkdir -p resume_parser && cd resume_parser
touch parser.py .env
mkdir -p input output
把PDF文件丢进 input 文件夹,解析结果会自动输出到 output 文件夹。
第三步:编写解析脚本 parser.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import re
import pdfplumber
import pandas as pd
from datetime import datetime
from pathlib import Path
from dotenv import load_dotenv
load_dotenv()
INPUT_DIR = "input"
OUTPUT_DIR = "output"
# 常见关键字段正则模式
FIELDS = {
"姓名": r"(?:姓名|名字|称谓)\s*[::]?\s*(\w{2,6})",
"电话": r"(?:电话|手机|Tel|Mobile)\s*[::]?(\d{11}|\+\d{1,3}-?\d{3,4}-?\d{4,7})",
"邮箱": r"\b([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,})\b",
"学历": r"(?:学历|学位|教育程度)[::]?(?:本科|硕士|博士|大专|学士)",
}
def extract_text_from_pdf(pdf_path):
"""从PDF提取全文文本"""
with pdfplumber.open(pdf_path) as pdf:
text = ""
for page in pdf.pages:
page_text = page.extract_text()
if page_text:
text += page_text + "\n"
return text
def extract_fields(text):
"""从文本中提取结构化字段"""
result = {}
for field_name, pattern in FIELDS.items():
matches = re.search(pattern, text, re.IGNORECASE | re.UNICODE)
if matches:
result[field_name] = matches.group(1).strip()
else:
result[field_name] = ""
# 尝试提取公司名和职位(更宽松的模式)
company_match = re.search(r"(?:任职单位|公司名称|Current Employer)[::]?([\w\s一二三四五六七八九十]+?)[:\n])", text)
if company_match:
result["公司"] = company_match.group(1).strip()[:50]
else:
result["公司"] = ""
pos_match = re.search(r(?:职位名称|岗位)[::]?([\w\s]+?)[:\n])", text)
if pos_match:
result["职位"] = pos_match.group(1).strip()[:50]
else:
result["职位"] = ""
return result
def process_resume(pdf_path, output_dir):
"""处理单个PDF文件"""
filename = pdf_path.stem
text = extract_text_from_pdf(pdf_path)
fields = extract_fields(text)
fields["文件路径"] = str(pdf_path)
fields["提取时间"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return fields
def main():
"""主程序入口"""
input_dir = Path(INPUT_DIR)
output_dir = Path(OUTPUT_DIR)
output_dir.mkdir(exist_ok=True)
if not input_dir.exists():
print(f"❌ 目录不存在: {input_dir}")
return
pdf_files = list(input_dir.glob("*.pdf")) + list(input_dir.glob("*.PDF"))
if not pdf_files:
print(f"⚠️ {input_dir} 目录下没有找到PDF文件")
return
print(f"📄 发现 {len(pdf_files)} 个PDF文件,开始处理...")
results = []
for pdf_file in pdf_files:
try:
result = process_resume(pdf_file, output_dir)
results.append(result)
print(f"✅ {pdf_file.name}: 提取成功 ({len(result)} 个字段)")
except Exception as e:
print(f"❌ {pdf_file.name}: 解析失败 - {str(e)}")
if results:
df = pd.DataFrame(results)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = output_dir/f"resumes_{timestamp}.xlsx"
df.to_excel(output_file, index_max=False, engine="openpyxl")
print(f"\n🎉 完成!共解析 {len(results)} 份简历")
print(f"📁 保存至: {output_file}")
# 也导出CSV方便打开
csv_path = output_dir/f"resumes_{timestamp}.csv"
df.to_csv(csv_path, index=False, encoding="utf-8-sig")
print(f"📁 CSV版本: {csv_path}")
if __name__ == "__main__":
main()
代码约200行,核心逻辑很清晰:遍历PDF文件 → 提取文本 → 用正则匹配关键字段 → 汇总成DataFrame → 导出Excel。
第四步:测试运行
先把一些PDF简历放进 input 文件夹,然后运行:
python parser.py
如果看到类似这样的输出就说明跑成功了:
📄 发现 3 个PDF文件,开始处理...
✅ resume_zhang.pdf: 提取成功 (8 个字段)
✅ resume_li.pdf: 提取成功 (8 个字段)
✅ resume_wang.pdf: 提取成功 (8 个字段)
🎉 完成!共解析 3 份简历
📁 保存至: output/resumes_20260727_103000.xlsx
📁 CSV版本: output/resumes_20260727_103000.csv
打开生成的Excel文件,你会看到清晰的表格,每一列对应一个字段,每一行是一份简历。
运行效果
生成的Excel表长这样:
| 文件名 | 姓名 | 电话 | 邮箱 | 学历 | 公司 | 职位 | 提取时间 |
|---|---|---|---|---|---|---|---|
| resume_zhang.pdf | 张三 | 13800138000 | zhangsan@email.com | 硕士 | 腾讯科技 | 后端工程师 | 2026-07-27 10:30:00 |
| resume_li.pdf | 李四 | 13900139000 | lisi@email.com | 本科 | 阿里巴巴 | 产品经理 | 2026-07-27 10:30:01 |
| … | … | … | … | … | … | … | … |
带中文的PDF文本提取效果最好。如果是扫描件图片形式的PDF,需要先做OCR识别,这个版本不支持。
优化方向
解析器跑通之后,还有很大扩展空间:
接入AI深度理解:对匹配度低的字段调用LLM辅助判断,比如从一段描述中提取"期望薪资"这种非标准字段
自定义字段模板:让用户自己编辑正则表达式模板,适配不同公司的简历格式需求
批量去重合并:同一候选人的多轮简历自动合并,保留最新信息
Web界面封装:用Streamlit或FastAPI搭个网页版,拖拽文件就能用,不用敲命令
集成飞书/钉钉通知:解析完成后自动推送结果到企业通讯工具
增加查重功能:用相似度算法检测重复投递的简历
支持DOCX/Word格式扩展:除了PDF,顺便也把Office文档支持加上
核心思路不变:先做规则匹配的baseline,再用AI补充模糊场景。简单问题简单解决,复杂问题留给大模型。
把你的第一份PDF扔进 input 文件夹,跑看看效果如何?遇到格式奇怪的简历,记得回来调正则表达式——这才是真实的工程过程。
这篇文章对你有帮助吗?