简历信息提取(一)
0 引言信息抽取任务旨在从非结构化的自然语言文本中提取结构化信息。在本系列项目中,将讨论如何又好又快地实现一个简历信息提取任务。作为该系列文章的第一篇,我们将首先从数据处理着手,探讨Word、PDF格式文档信息提取的一些基本方法。数据集简介本文使用的简历数据集是脱敏之后的中文人才简历数据和标注数据。标注类别包括:姓名、出生年月、性别、电话、最高学历、籍贯、落户市县、政治面貌、毕业院校、工作单位、工
0 引言
信息抽取任务旨在从非结构化的自然语言文本中提取结构化信息。在本系列项目中,将讨论如何又好又快地实现一个简历信息提取任务。
作为该系列文章的第一篇,我们将首先从数据处理着手,探讨Word、PDF格式文档信息提取的一些基本方法。
数据集简介
本文使用的简历数据集是脱敏之后的中文人才简历数据和标注数据。
标注类别包括:姓名、出生年月、性别、电话、最高学历、籍贯、落户市县、政治面貌、毕业院校、工作单位、工作内容、职务、项目名称、项目责任、学位、毕业时间、工作时间、项目时间共18个字段。
在训练数据集中,每个“毕业院校、学位、毕业时间”为一组,以“教育经历”列表给出;每个“工作单位、工作内容、职务、工作时间”为一组,以“工作经历”列表给出;每个“项目名称、项目责任、项目时间”为一组,以“项目经历”列表给出。
训练数据同时给出了PDF和Word格式。
1 word文档信息提取
1.1 认识.docx
格式
现在.docx
格式是我们最常见到的一种Word文档格式了,它是微软采用类XML格式标准定义的Word文件。
正因如此,相比早期的.doc
文件,.docx
文件的兼容性大幅提升。
那么,.docx
文件又是如何封装的?.docx
实际上是一个zip的压缩文件,比如我们任选一个.docx
文件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tDww3qlB-1636944651045)(https://ai-studio-static-online.cdn.bcebos.com/acc7880fa91247a5a2e3fa8e7c5d3670aacca1de565f4c84ad3eb59072898d34)]
再把它的文件名后缀直接修改为.zip
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nb8vRFMz-1636944651047)(https://ai-studio-static-online.cdn.bcebos.com/14181f975e9848699ec46d5462ea9b87c12ed7c9ccb74022a865ab353d6b25f9)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RG7tYJCb-1636944651048)(https://ai-studio-static-online.cdn.bcebos.com/ae2c0b4c43074dab8f07bda0e0ec7d596809c919ef6f4fb6bae0f83484460c22)]
打开这个压缩包,我们会看到,其实文档的正文,是以XML格式表示的,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h3PlibKu-1636944651049)(https://ai-studio-static-online.cdn.bcebos.com/2ad3cac751834ffc987521534a5f05c07b3866a1f7f9460a8db4367ccea01e13)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m00tpBaH-1636944651050)(https://ai-studio-static-online.cdn.bcebos.com/000a892628ac40dba8aeb042b5e6d951772bd02d00c74c2abf630b42dfab9f03)]
因此,其实除了python-docx
库之外,BeautifulSoup
也可以用来提取Word文档信息。
1.2 提取word文档信息
1.2.1 用python-docx
提取文档信息
python-docx
其实在项目PaddleHub机器翻译:文档的批量翻译中提到过
这里不做过多赘述,我们直奔主题,选取一份word简历文档,尝试提取信息。
# 解压缩数据集
!unzip data/data40148/train_20200121.zip
# 安装依赖库
!pip install python-docx
from docx import Document
from docx.shared import Inches
def get_paragraphs_text(path):
"""
获取所有段落的文本
:param path: word路径
:return: list类型,如:
['Test', 'hello world', ...]
"""
document = Document(path)
# 有的简历是表格式样的,因此,不仅需要提取正文,还要提取表格
col_keys = [] # 获取列名
col_values = [] # 获取列值
index_num = 0
# 表格提取中,需要添加一个去重机制
fore_str = ""
cell_text = ""
for table in document.tables:
for row_index,row in enumerate(table.rows):
for col_index,cell in enumerate(row.cells):
if fore_str != cell.text:
if index_num % 2==0:
col_keys.append(cell.text)
else:
col_values.append(cell.text)
fore_str = cell.text
index_num +=1
cell_text += cell.text + '\n'
# 提取正文文本
paragraphs_text = ""
for paragraph in document.paragraphs:
# 拼接一个list,包括段落的结构和内容
paragraphs_text += paragraph.text + "\n"
return cell_text, paragraphs_text
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IjR1FCv3-1636944651051)(https://ai-studio-static-online.cdn.bcebos.com/d65ae7bb5eab45e0901df04f08837eb21e0968a120f6402cac257da88b8d99aa)]
# 提取文档信息,这是一个表格式简历
cell_text, paragraphs_text = get_paragraphs_text('resume_train_20200121/docx/0043e770a330.docx')
print(cell_text, paragraphs_text)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9GJ9ghq-1636944651051)(https://ai-studio-static-online.cdn.bcebos.com/c0cc78f2688c4f9ab4f9934ea2584b946826aafa4d914d8a8246882e94a71f1c)]
# 提取文档信息,这是一个表格正文混搭式简历(会出现一些混乱的情况,因为在这个文件里,标题是以表格形式存在)
cell_text, paragraphs_text = get_paragraphs_text('resume_train_20200121/docx/0052b7958e89.docx')
print(cell_text, paragraphs_text)
杜素宁
MOBILE : 15904130130
E-MAIL:0da08x@163.com
Address:云南省昭通市
个人信息
民族:汉
籍贯:云南省昭通市
性别:女
年龄: 18
教育经历
2008.08-2012.08
北方工业大学
食品科学与工程
学士学位
主要经历
Project Experience
1997.06-2010.07
江苏华英企业管理股份有限公司
水处理工程师
1991年12月-2012年09月
和宇健康科技股份有限公司
市场营销专员
2007/05-2010/03
深圳市有棵树科技有限公司
拼多多运营
个人技能
Personal Skills
个人荣誉
Personal Honor
工作经历:
工作内容:
1.负责部门内日常用品的采购;2.做好与公司内其他部门的对接工作;3.协助部门进行办公环境管理和后勤管理工作;4.销售人员与公司的信息交流,随时保持与市场销售人员的电话沟通,销售政策及公司文件的及时传达。5.领导交办的其他工作
工作经历:
工作内容:
1、做好消费宾客的迎、送接待工作,接受宾客各种渠道的预定并加以落实;2、礼貌用语,详细做好预订记录;3、了解和收集宾客的建议和意见并及时反馈给上级领导;4、以规范的服务礼节,树立公司品牌优质,文雅的服务形象。
工作经历:
工作内容:
1.负责规定区域的产品销售,做好产品介绍,确认订单,回款等销售相关工作;2.做好客户背景资料调查,竞争对手分析,产品适用性分析;3.按公司规定完成SalesPipeline信息记录
吃饭
优秀学生干部
1.2.2 用BeautifulSoup提取Word文档信息
如果说这种方法有什么缺点的话,就是遇到一些艺术字等标题,与后面的文字从语义上是连续的,但是XML格式不连续。
# 安装依赖库
!pip install bs4
from zipfile import ZipFile
from bs4 import BeautifulSoup
document = ZipFile('resume_train_20200121/docx/0052b7958e89.docx')
xml = document.read("word/document.xml")
wordObj = BeautifulSoup(xml.decode("utf-8"))
texts = wordObj.findAll("w:t")
for text in texts:
print(text.text)
杜素宁
MOBILE
:
15904130130
E-MAIL
:
0da08x@163.com
A
ddress
:云南省昭通市
个人信息
民族:
汉
籍贯:
云南省昭通市
性别:
女
年龄
: 18
教育经历
2008.08-2012.08
北方工业大学
食品科学与工程
学士学位
主要经历
P
roject Experience
工作经历:
1997.06-2010.07
江苏华英企业管理股份有限公司
水处理工程师
工作内容:
1.负责部门内日常用品的采购;2.做好与公司内其他部门的对接工作;3.协助部门进行办公环境管理和后勤管理工作;4.销售人员与公司的信息交流,随时保持与市场销售人员的电话沟通,销售政策及公司文件的及时传达。5.领导交办的其他工作
工作经历:
1991年12月-2012年09月
和宇健康科技股份有限公司
市场营销专员
工作内容:
1、做好消费宾客的迎、送接待工作,接受宾客各种渠道的预定并加以落实;2、礼貌用语,详细做好预订记录;3、了解和收集宾客的建议和意见并及时反馈给上级领导;4、以规范的服务礼节,树立公司品牌优质,文雅的服务形象。
工作经历:
2007/05-2010/03
深圳市有棵树科技有限公司
拼多多运营
工作内容:
1.负责规定区域的产品销售,做好产品介绍,确认订单,回款等销售相关工作;2.做好客户背景资料调查,竞争对手分析,产品适用性分析;3.按公司规定完成SalesPipeline信息记录
个人技能
Personal
Skills
吃饭
个人荣誉
P
ersonal Honor
优秀学生干部
2 使用pdfplumber库提取PDF信息
!pip install pdfplumber
import pdfplumber
import pandas as pd
with pdfplumber.open("resume_train_20200121/pdf/0052b7958e89.pdf") as pdf:
page = pdf.pages[0] # 第一页的信息
text = page.extract_text()
print(text)
杜素宁
MOBILE : 15904130130
E-MAIL:0da08x@163.com
Address:云南省昭通市
个人信息
民族:汉 籍贯:云南省昭通市 性别:女 年龄: 18
教育经历
2008.08-2012.08 北方工业大学 食品科学与工程 学士学位
主要经历
Project Experience
工作经历:
1997.06-2010.07 江苏华英企业管理股份有限公司 水处理工程师
工作内容:
1.负责部门内日常用品的采购;2.做好与公司内其他部门的对接工作;3.协助部门进行办公环境管理和后勤管理工作;4.销
售人员与公司的信息交流,随时保持与市场销售人员的电话沟通,销售政策及公司文件的及时传达。5.领导交办的其他工作
工作经历:
1991年12月-2012年 和宇健康科技股份有限公司 市场营销专员
09月
工作内容:
1、做好消费宾客的迎、送接待工作,接受宾客各种渠道的预定并加以落实;2、礼貌用语,详细做好预订记录;3、了解和
收集宾客的建议和意见并及时反馈给上级领导;4、以规范的服务礼节,树立公司品牌优质,文雅的服务形象。
工作经历:
2007/05-2010/03 深圳市有棵树科技有限公司 拼多多运营
工作内容:
1.负责规定区域的产品销售,做好产品介绍,确认订单,回款等销售相关工作;2.做好客户背景资料调查,竞争对手分析,
产品适用性分析;3.按公司规定完成SalesPipeline信息记录
with pdfplumber.open("resume_train_20200121/pdf/0052b7958e89.pdf") as pdf:
page = pdf.pages[0] # 第一页的信息
table = page.extract_tables()
for t in table:
# 得到的table是嵌套list类型,转化成DataFrame更加方便查看和分析
df = pd.DataFrame(t[1:], columns=t[0])
print(t)
[['个人信息', None, None, '', None, None, None], ['民族:汉', '', '籍贯:云南省昭通市', None, '', '性别:女', '年龄: 18']]
[['教育经历', None, None, '', None, None], ['2008.08-2012.08', '', '北方工业大学', None, '食品科学与工程', '学士学位']]
[['主要经历 \nProject Experience', '']]
[['1997.06-2010.07', '江苏华英企业管理股份有限公司', '水处理工程师']]
[['', '1991年12月-2012年', '', '和宇健康科技股份有限公司', '市场营销专员'], [None, '09月', None, None, None]]
[['2007/05-2010/03', '深圳市有棵树科技有限公司', '拼多多运营']]
因此,对于同时有表格(标题用表格表示)和正文交错的文档,pdfplumber也能很好地识别,如果是布局标准的纵向PDF,效果还是非常稳定的。
3 通过PPOCR识别PDF
这个方式看起来有点绕,如果可以直接识别PDF和word,为什么还要转图片用OCR呢?
不过,在很多时候,它还是一个很必要的补充手段,毕竟,如果简历的PDF是那种扫描式的,甚至word文档万一就是个图片……
手段多一些,总是有备无患的。
在本文中,我们尝试的是PP-Structure工具包,它提供了PDF图片表格一键提取解决方案。
# 安装依赖库
# pywt可能要重启内核
!pip install pywt -i https://mirror.baidu.com/pypi/simple
!pip install "paddleocr>=2.2" --no-deps -r requirements.txt
# 安装依赖库
!pip install -U https://paddleocr.bj.bcebos.com/whl/layoutparser-0.0.0-py3-none-any.whl
!pip install PyMuPDF
import datetime
import os
import fitz # fitz就是pip install PyMuPDF
import cv2
import shutil
from paddleocr import PPStructure,draw_structure_result,save_structure_res
import numpy as np
3.1 PDF批量转图片
def pyMuPDF_fitz(pdfPath, imagePath):
startTime_pdf2img = datetime.datetime.now() # 开始时间
print("imagePath=" + imagePath)
pdfDoc = fitz.open(pdfPath)
for pg in range(pdfDoc.pageCount):
page = pdfDoc[pg]
rotate = int(0)
# 每个尺寸的缩放系数为4,这将为我们生成分辨率提高4的图像。
# 此处若是不做设置,默认图片大小为:792X612, dpi=96
zoom_x = 4 # (1.33333333-->1056x816) (2-->1584x1224)
zoom_y = 4
mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
pix = page.getPixmap(matrix=mat, alpha=False)
if not os.path.exists(imagePath): # 判断存放图片的文件夹是否存在
os.makedirs(imagePath) # 若图片文件夹不存在就创建
pix.writePNG(imagePath + '/' + 'images_%s.png' % pg) # 将图片写入指定的文件夹内
endTime_pdf2img = datetime.datetime.now() # 结束时间
print('pdf转图片时间=', (endTime_pdf2img - startTime_pdf2img).seconds)
pdfDir = './resume_train_20200121/pdf'
def gci(filepath):
#遍历filepath下所有文件
files = os.listdir(filepath)
for fi in files:
# 将转换的图片保存到对应imgs的对应子目录下
pyMuPDF_fitz(os.path.join(filepath,fi), os.path.join('imgs',fi[:-4]))
# 遍历PDF文件并转换图片。如果读者觉得转换时间比较长,可以提前中止cell。
gci(pdfDir)
3.2 对不同式样简历提取信息
下面这两张简历我们可以看出,对于一些表格式简历,版面分析会将其判定为表格。
其它的简历,可能被认为版面上是图片甚至既没有图片也没有表格。
如果使用PP-Structure,对这几种检测结果,需要分别进行后处理。
import cv2
import layoutparser as lp
image = cv2.imread('imgs/0043e770a330/images_0.png')
image = image[..., ::-1]
# 加载模型
model = lp.PaddleDetectionLayoutModel(config_path="lp://PubLayNet/ppyolov2_r50vd_dcn_365e_publaynet/config",
threshold=0.5,
label_map={0: "Text", 1: "Title", 2: "List", 3:"Table", 4:"Figure"},
enforce_cpu=False,
enable_mkldnn=True)
# 检测
layout = model.detect(image)
# 显示结果
show_img = lp.draw_box(image, layout, box_width=3, show_element_type=True)
show_img
from bs4 import BeautifulSoup
import re
# 表格类的预测结果已经封装在HTML标签中了
table_engine = PPStructure(show_log=True)
img = cv2.imread('imgs/0043e770a330/images_0.png')
result = table_engine(img)
result[0]['res']
# 折行问题需要在后续进一步解决
html = BeautifulSoup(result[0]['res'],'html.parser', from_encoding='utf-8')
list(html.strings)
['姓名',
'郝淑宁',
'性别',
'男',
'出生日期',
'2000.04',
'民族',
'汉族',
'联系电话',
'13602173036',
'籍贯',
'黑龙江省双鸭山「邮箱 市',
'bhluo@live.com',
'教育背景',
'毕业时间:',
'2012.08 - 2016.08',
'毕业学校:北京政法职业学院',
'学历/学位:大学本科/学士学位',
'专业:动物生产',
'工作经验',
'时间:1991年07月-2016年12月',
'部门:研发部',
'公司:江苏达科信息科技有限公司',
'职位:渠道商务',
'1、申请票据,购***,准备和报送会计报表,会报税及报税流程;2、现金及银行收付处理,制作记帐',
'凭证,银行对帐,单据审核,开具与保管发票;3、协助财会文件的准备、归档和保管;4、固定资产和',
'工作;',
'低值易耗品的登记和管理;5、负责与银行、税务等部门的对外联络;6、协助领导完成其他日常事务性',
'时间:1992年05月-2015年05月',
'公司:盛趣信息技术有限公司部门:研发部',
'职位:商场空调工5.5k',
'1、根据公司制定的目标,制定有效销售计划,开发客户,完成销售任务;2、关注市场变化,收集有效',
'的市场信息,为公司的销售策略作参考资料依据;3、做好客户管理工作,根据不同客户的需求特点和 相关的信息、数据,提供解决方案;4、统筹客户维系工作,做好客户拜访计划,并按计划进行拜访,',
'推进项目;5、协助领导做好公司其他工作。',
'时间:2006.06-2018.06',
'公司:广州市华粤行仪器有限公司',
'部门:研发部',
'职位:Golang开发工程师',
'1、登记收集资料,整理文件表格;2、辅助就业指导老师为鹏程学员推荐工作;3、发布招聘信息,与',
'鹏程学员互动;4、对接好企业,为鹏程学员推荐心仪工作到面到岗服务。',
'项目经验',
'2001.12-2012.01 1、协助制定市场活动计划,组织落实市场活动;2、负责展会活动策划与相关活动支持,市场推广资料',
'珠三角最低工资标准的执行、影响与对策研究']
import cv2
import layoutparser as lp
image = cv2.imread('imgs/0052b7958e89/images_0.png')
image = image[..., ::-1]
# 加载模型
model = lp.PaddleDetectionLayoutModel(config_path="lp://PubLayNet/ppyolov2_r50vd_dcn_365e_publaynet/config",
threshold=0.5,
label_map={0: "Text", 1: "Title", 2: "List", 3:"Table", 4:"Figure"},
enforce_cpu=False,
enable_mkldnn=True)
# 检测
layout = model.detect(image)
# 显示结果
show_img = lp.draw_box(image, layout, box_width=3, show_element_type=True)
show_img
with open(os.path.join('data', 'res.txt'), 'w', encoding='utf8') as f:
for img in os.listdir('imgs/0043e770a330'):
img_path = os.path.join(fi_d,img)
img = cv2.imread(img_path)
result = table_engine(img)
print(result[0]['res'])
for box, rec_res in zip(result[0]['res'][0], result[0]['res'][1]):
f.write('{}\t{}\n'.format(np.array(box).reshape(-1).tolist(), rec_res))
table_engine = PPStructure(show_log=True)
img = cv2.imread('imgs/0052b7958e89/images_0.png')
result = table_engine(img)
result[0]['res']
for box, rec_res in zip(result[0]['res'][0], result[0]['res'][1]):
print(rec_res[0])
杜素宁
MOBILE:15904130130
E-MAIL:0da08x@163.com
Address:云南省昭通市
个人信息
性别:女
民族:汉
籍贯:云南省昭通市
年龄:18
教育经历
北方工业大学
食品科学与工程
2008.08-2012.08
学士学位
主要经历
Project Experience
工作经历:
1997.06-2010.07
江苏华英企业管理股份有限公司
水处理工程师
工作内容:
1.负责部门内日常用品的采购;2.做好与公司内其他部门的对接工作;3.协助部门进行办公环境管理和后勤管理工作;4.销
售人员与公司的信息交流,随时保持与市场销售人员的电话沟通,销售政策及公司文件的及时传达。5.领导交办的其他工作
工作经历:
1991年12月-2012年
和宇健康科技股份有限公司
市场营销专员
09月
工作内容:
1、做好消费宾客的迎、送接待工作,接受宾客各种渠道的预定并加以落实;2、礼貌用语,详细做好预订记录;3、了解和
收集宾客的建议和意见并及时反馈给上级领导;4、以规范的服务礼节,树立公司品牌优质,文雅的服务形象
工作经历:
2007/05-2010/03
深圳市有棵树科技有限公司
拼多多运营
工作内容:
1.负责规定区域的产品销售,做好产品介绍,确认订单,回款等销售相关工作;2.做好客户背景资料调查,竞争对手分析
产品适用性分析;3.按公司规定完成SalesPipeline信息记录
4 小结
在本文中,我们探索并比较了Word、PDF、图片格式的简历文件信息提取方法,在后续项目中,将结合PaddleNLP的信息提取技术,尝试将非结构化的简历文件,提取成标注文件指定的格式,并验证性能。
更多推荐
所有评论(0)