实验用到的是Python爬虫技术,实现爬取和可视化的思想有:
实验知识点
-
使用request.get(url)获取网页的HTML。
-
对返回回来的HTML代码进行正则表达式匹配提取网页中需要的数据和文本。
正则表达式: -
re 模块使 Python 语言拥有全部的正则表达式功能。
-
Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。
-
re.sub(pattern, repl, string, count=0, flags=0)
参数: -
pattern : 正则中的模式字符串。
-
repl : 替换的字符串,也可为一个函数。
-
string : 要被查找替换的原始字符串。
-
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
-
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
-
re.compile(pattern[, flags])
参数: -
pattern : 一个字符串形式的正则表达式
-
flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
-
re.I 忽略大小写
-
re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
-
re.M 多行模式
-
re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
-
re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
-
re.X 为了增加可读性,忽略空格和 # 后面的注释
-
Findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
findall(string[, pos[, endpos]]) -
参数:
string : 待匹配的字符串。
pos : 可选参数,指定字符串的起始位置,默认为 0。
endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。 -
使用字典保存提取到的想要的数据。
-
把提取到的信息保存到XLS文件中(Excel):
用到的是xlwt模块,xlwt.workbook(encoding=‘utf-8’)去创建保存的编码格式,使用workbook.add_sheet()去创建XLS表,使用worksheet.write()对表进行填写,然后在用for循环把提取到的内容按创建的表头,正确的填入对于的列中。 -
精确提取个人经历,并且用AGraph对其进行可视化出来,思维导图显示个人经历;用到for循环去处理第一次提取出来的粗糙数据,把数据分别保存在变量中,再对这些数据进行思维导图的实现。
实验步骤
爬取简历:
粗糙爬取部分代码展示
分析心得:遇到蛮多坑的,提取不到数据,提取到的数据为空,匹配不准确,HTML中包含一些特殊字符,需要去排除,或者后期把特殊字符删掉,比如空格字符,乱码,其他无关字符;还有正则表达式的书写,这是最难的一点,需要写得和返回的HTML相匹配,而不是在网页控制台上的,会有一些出入。
保存为xls部分代码
分析心得:由于数据比较多,在保持代码上就会看起来很多,特别是判断信息是否是在该列上,难道不大,就是比较繁琐。
数据可视化部分代码
分析心得:这在前面已经有过可视化的实现,这次就做的比较轻松一些,但是也有新的内容,就是在节点旁边添加附加的标注,这个我也是找了很久,找到了又存在和别用的可视化方法不同,label的设置调了很久。
实验效果图
实验代码
#实验三提取简历要素
import requests
import xlwt
import re
import os
import pygraphviz as pgv
def get_hdxw_all_report(url):
dic = {}
r = requests.get(url)#返回网页所有内容
r.encoding = "gbk"#编码
r.raise_for_status()#判别返回response类型状态,返回200正确否则会错误
matches = "x"
matches = re.findall('<td width="100".*?>姓名</td> <td .*?>(.*?)</td>',r.text)#不带括号为非匹配内容,匹配到的所有内容放到一个列表中
#['姓名','-']
# a=matches.group(1) 报错AttributeError: 'list' object has no attribute 'group'
# print(matches)
dic['姓名'] = matches
matches = re.findall('<td .*?> 国籍:</td> <td .*?>(.*?)</td>',r.text)#中间的空格是需要的,相当于HTML换行
dic['国籍'] = matches[0]
matches = re.findall('<td .*?> 目前所在地:</td> <td .*?>(.*?)</td>',r.text)
dic['目前所在地'] = matches[0]
matches = re.findall('<td .*?> 民族:</td> <td .*?>(.*?)</td>',r.text)
dic['民族'] = matches[0]
matches = re.findall('<td .*?> 户口所在地:</td> <td .*?>(.*?)</td>',r.text)
dic['户口所在地'] = matches[0]
matches = re.findall('<td .*?> 身材:</td> <td .*?>(.*?)</td> </tr>',r.text)
a = matches[0]#matches 30行会出现错误,
# strinfo = re.compile('')#创建模式对象
# b = strinfo.sub('', a)
a = a.replace(' ', ' ')#
a = a.replace('��', ' ')#用''代替'��'
dic['身材'] = a
matches = re.findall('<td .*?> 婚姻状况:</td> <td .*?>(.*?)</td>',r.text)
dic['婚姻状况'] = matches[0]
matches = re.findall('<td .*?>年龄:</td> <td .*?>(.*?)</td>',r.text)
dic['年龄'] = matches[0]
matches = re.findall('<td .*?>培训认证:</td> <td .*?>(.*?)</td>',r.text)
a = matches[0] #提取出来是&nbs;
strinfo = re.compile(' ||;|| ')#创建' '对象
b = strinfo.sub('', a)# 空格处理
# a=re.sub(' ','',a)也可以处理&nbsq空格,但是显示占位大
dic['培训认证'] = b
matches = re.findall('<td .*?>诚信徽章:</td> <td .*?>(.*?)</td>',r.text)
a = matches[0]
strinfo = re.compile(' ||;|| ')
b = strinfo.sub('', a)
dic['诚信徽章'] = b
matches = re.findall('<td .*?>人才类型:</td> <td .*?>(.*?)</td> ',r.text)
a = matches[0]
strinfo = re.compile('')
b = strinfo.sub('', a)
b = b.replace('��', ' ')
b = b.replace(' ', ' ')
dic['人才类型'] = b
matches = re.findall('<td .*?>应聘职位:</td> <td .*?>(.*?)</td> ',r.text)
a = matches[0]
strinfo = re.compile('\u3000')
b = strinfo.sub('', a)#a中用''替换'\u3000'
dic['应聘职位'] = b
matches = re.findall('<td .*?> 工作年限:</td> <td width="180">(.*?)</td>',r.text)
dic['工作年限'] = matches[0]
matches = re.findall('<td .*?> 职称:</td> <td>(.*?)</td>',r.text)
dic['职称'] = matches[0]
matches = re.findall(' <td .*?> 求职类型:</td> <td .*?>(.*?)</td>',r.text)
dic['求职类型'] = matches[0]
matches = re.findall('<td .*?> 可到职-</td> <td>(.*?)</td>',r.text)
dic['可到职'] = matches[0]
matches = re.findall('<td .*?> 月薪要求:</td> <td .*?>(.*?)</td>',r.text)
dic['月薪要求'] = matches[0]
matches = re.findall('<td .*?> 希望工作地区:</td> <td nowrap>(.*?)</td>',r.text)
dic['希望工作地区'] = matches[0]
matches = re.findall('<td .*?>个人工作经历:</td> <td colspan="3">(.*?)</td>',r.text)
a = matches[0]
strinfo = re.compile('  ||  ||<br>')
b = strinfo.sub('', a)
dic['个人工作经历'] = b
matches = re.findall('<td .*?> 毕业院校:</td> <td .*?>(.*?)</td>',r.text)
dic['毕业院校'] = matches[0]
matches = re.findall(' <td .*?> 最高学历:</td> <td width="180">(.*?)</td>',r.text)
dic['最高学历'] = matches[0]
matches = re.findall(' <td .*?> 毕业-</td> <td>(.*?)</td>',r.text)
dic['毕业'] = matches[0]
matches = re.findall('<td .*?> 所学专业一:</td> <td width="180">(.*?)</td>',r.text)
dic['所学专业一'] = matches[0]
matches = re.findall('<td .*?> 所学专业二:</td> <td>(.*?)</td>',r.text)
dic['所学专业二'] = matches[0]
matches = re.findall('<td .*?> 受教育培训经历:</td> <td colspan="3">(.*?)</td>',r.text)
a = matches[0]
strinfo = re.compile('<br\s*?/?>|| ||;||\u3000')
b = strinfo.sub('', a)
dic['受教育培训经历'] = b
matches = re.findall(
'<td width="100" align="right" bgcolor="#EEF4F9"> 外语:</td> <td width="180" bgcolor="#F4F7FA">(.*?)</td>',
r.text)
a = matches[0]
strinfo = re.compile('<br\s*?/?>|| ||\u3000')
b = strinfo.sub('', a)
dic['外语'] = b
matches = re.findall('<td align="right" bgcolor="#EEF4F9"> 国语水平:</td> <td bgcolor="#F4F7FA">(.*?)</td>',r.text)
dic['国语水平'] = matches[0]
matches = re.findall('<td align="right" bgcolor="#EEF4F9" width="100"> 粤语水平:</td> <td bgcolor="#F4F7FA">(.*?)</td>', r.text)
dic['粤语水平'] = matches[0]
matches = re.findall('<td bgcolor="E4EBF2" height="18"><b> 工作能力及其他专长</b></td> </tr> </table> <table width="580" border="0" cellspacing="1" cellpadding="2" bgcolor="#CADADF" align="center"> <tr> <td width="100" bgcolor="#EEF4F9"></td> <td bgcolor="#F4F7FA">(.*?) </td>',r.text)
a = matches[0]
strinfo = re.compile('</?\w+[^>]*>|| || ')
b = strinfo.sub('', a)
dic['工作能力及其他专长'] = b
matches = re.findall('<b> 详细个人自传</b></td> </tr> </table> <table width="580" border="0" cellspacing="1" cellpadding="2" bgcolor="#CADADF" align="center"> <tr> <td width="100" bgcolor="#EEF4F9"></td> <td bgcolor="#F4F7FA">(.*?)</td>',r.text)
a = matches[0]
strinfo = re.compile('</?\w+[^>]*>|| ||;|| ')
b = strinfo.sub('', a)
dic['详细个人自传'] = b
print(dic)#输出dic{}
#存为xls(excel)
workbook = xlwt.Workbook(encoding='utf-8')
worksheet = workbook.add_sheet('sheet1')
# 设置表头
worksheet.write(0, 0, label='姓名')
worksheet.write(0, 1, label='国籍')
worksheet.write(0, 2, label='目前所在地')
worksheet.write(0, 3, label='民族')
worksheet.write(0, 4, label='户口所在地')
worksheet.write(0, 5, label='身材')
worksheet.write(0, 6, label='婚姻状况')
worksheet.write(0, 7, label='年龄')
worksheet.write(0, 8, label='培训认证')
worksheet.write(0, 9, label='诚信徽章')
# ----------------------------------
worksheet.write(0, 10, label='人才类型')
worksheet.write(0, 11, label='应聘职位')
worksheet.write(0, 12, label='工作年限')
worksheet.write(0, 13, label='职称')
worksheet.write(0, 14, label='求职类型')
worksheet.write(0, 15, label='可到职')
worksheet.write(0, 16, label='月薪要求')
worksheet.write(0, 17, label='希望工作地区')
worksheet.write(0, 18, label='个人工作经历')
worksheet.write(0, 19, label='毕业院校')
# ----------------------------
worksheet.write(0, 20, label='最高学历')
worksheet.write(0, 21, label='毕业')
worksheet.write(0, 22, label='所学专业一')
worksheet.write(0, 23, label='所学专业二')
worksheet.write(0, 24, label='受教育培训经历')
worksheet.write(0, 25, label='外语')
worksheet.write(0, 26, label='国语水平')
worksheet.write(0, 27, label='粤语水平')
worksheet.write(0, 28, label='工作能力及其他专长')
worksheet.write(0, 29, label='详细个人自传')
flag = os.path.exists("OK.xls")
val = 1
if flag is False:
for key in dic:
if key == '姓名':
worksheet.write(val, 0, dic.get(key))
if key == '国籍':
worksheet.write(val, 1, dic.get(key))
if key == '目前所在地':
worksheet.write(val, 2, dic.get(key))
if key == '民族':
worksheet.write(val, 3, dic.get(key))
if key == '户口所在地':
worksheet.write(val, 4, dic.get(key))
if key == '身材':
worksheet.write(val, 5, dic.get(key))
if key == '婚姻状况':
worksheet.write(val, 6, dic.get(key))
if key == '年龄':
worksheet.write(val, 7, dic.get(key))
if key == '培训认证':
worksheet.write(val, 8, dic.get(key))
if key == '诚信徽章':
worksheet.write(val, 9, dic.get(key))
if key == '人才类型':
worksheet.write(val, 10, dic.get(key))
if key == '应聘职位':
worksheet.write(val, 11, dic.get(key))
if key == '工作年限':
worksheet.write(val, 12, dic.get(key))
if key == '职称':
worksheet.write(val, 13, dic.get(key))
if key == '求职类型':
worksheet.write(val, 14, dic.get(key))
if key == '可到职':
worksheet.write(val, 15, dic.get(key))
if key == '月薪要求':
worksheet.write(val, 16, dic.get(key))
if key == '希望工作地区':
worksheet.write(val, 17, dic.get(key))
if key == '个人工作经历':
worksheet.write(val, 18, dic.get(key))
if key == '毕业院校':
worksheet.write(val, 19, dic.get(key))
if key == '最高学历':
worksheet.write(val, 20, dic.get(key))
if key == '毕业':
worksheet.write(val, 21, dic.get(key))
if key == '所学专业一':
worksheet.write(val, 22, dic.get(key))
if key == '所学专业二':
worksheet.write(val, 23, dic.get(key))
if key == '受教育培训经历':
worksheet.write(val, 24, dic.get(key))
if key == '外语':
worksheet.write(val, 25, dic.get(key))
if key == '国语水平':
worksheet.write(val, 26, dic.get(key))
if key == '粤语水平':
worksheet.write(val, 27, dic.get(key))
if key == '工作能力及其他专长':
worksheet.write(val, 28, dic.get(key))
if key == '详细个人自传':
worksheet.write(val, 29, dic.get(key))
#如果再爬一个网站就要修改一下文件
workbook.save('OK.xls')
return dic
#求职意向及工作经历,教育背景
def get_time_thing(who):
b=who['个人工作经历']
c=who['受教育培训经历']
#匹配时间和文字
#pattern=re.compile()#数字范围\u0030-\u0039 中文范围\u4e00-\u9fa5
# it = re.finditer(r"\d+",c)
# for i in it:
# ctime[i]=match.group()
for each in who:
if '-'or'.' in each:
pattern = re.compile(r'\d+[.-]\d+[.-]\d+[.-]\d+') # ['','']类型或返回空
else:
pattern = re.compile(r'\d+')
str_content = re.compile('[\u4e00-\u9fa5][^0-9]+')#中文范围\u4e00-\u9fa5必要前面时间可能有.-
btime = pattern.findall(b)
bstar = str_content.findall(b)
ctime = pattern.findall(c)
cstar = str_content.findall(c)
# print(b)
# print(c)
print(btime)
print(bstar)
print(ctime)
print(cstar)
# 有向图 非简单图,不同级节点最小间距,线条类型,合并线条
G = pgv.AGraph(directed=True, strict=False, ranksep=0.2, splines='spline', concenyrate=True, rounded=True,
expected=2, fontname="FangSong", encoding='UTF-8')
G.graph_attr['epsilon'] = '0.001'
alongs = len(cstar) # 长度
for i in range(alongs): # 不能直接alongs进行迭代TypeError: 'int' object is not iterable
# 添加节点
G.add_node(cstar[i],color='#ffffff', fontname="FangSong", fontsize=18,encoding='UTF-8')
# 添加边
G.add_edge('start',cstar[0], color='#7F01FF', arrowsize=0.8,label=ctime[0])
G.add_edge([cstar[0], cstar[1]],color='#7F01FF', arrowsize=0.8,label=ctime[1])
G.add_edge([cstar[1], cstar[2]],color='#7F01FF', arrowsize=0.8,label=ctime[2])
G.layout()
G.draw("简历提取要素3.png", prog="dot") # 乱码解决,节点指定字体,保存为utf-8
next_url = "http://www.gerenjianli.com/resume/class/11749.htm" #11746、11749、11750测试成功。
a=get_hdxw_all_report(next_url)
b=get_hdxw_all_report("http://www.gerenjianli.com/resume/class/11746.htm")
c=get_hdxw_all_report("http://www.gerenjianli.com/resume/class/11750.htm")
#经历
get_time_thing(c)
#get_time_thing(a)