利用正则表达式提取签到卡机数据中的人员考勤情况
我们这里已经获取到了某单位签到卡机导出的数据和单位人员通讯录。
其中签到机导出数据格式为.txt,内容如下图:
其中有价值的信息就数每行的time,id,name了,所以第一步要做的就是从文本中提取出所有time,id,name的数据。而需要从文本中筛选需要的信息,最好的办法自然是使用正则表达式。
这里首先要介绍下正则表达式模块re中的一个比较好用的函数findall,通过输入help(re.findall),可以看到函数的信息如下:
findall(pattern, string, flags=0)
Return a list of all non-overlapping matches in the string.
If one or more groups are present in the pattern, return a
list of groups; this will be a list of tuples if the pattern
has more than one group.
Empty matches are included in the result.
函数会返回值字符串中所有符合匹配条件结果的一个列表,如果是多个匹配条件,则返回包含所有符合条件的值的元组的列表。
建立一个py文件,导入需要用到的模块 re(正则表达式),datetime(处理日期格式需要用到),xlwt(最后需要将结果保存至excel用来展示),读取签到机数据文件的内容,利用正则表达式筛选数据字段 time="(.+?)" id="(.+?)" name="(.+?)",findall将提取每行标记括号的部分返回一个元组,代码如下:
1 import re 2 import datetime 3 import xlwt 4 5 6 def get_record(filename): 7 with open(filename,'r') as f: 8 content = f.read() 9 infor_list = re.findall(r'time="(.+?)" id="(.+?)" name="(.+?)"',content) 10 return infor_list 11 12 if __name__ == "__main__": 13 list_infor = get_record('TIME182.TXT') 14 print list_infor
运行后结果如下:
可以看出,需要的数据全部已经提取成功。
下一步,需要做的就是把这些数据与单位通讯录中的人名和签到机数据所涉及的日期进行关联后以一种比较直观的方式展现出来。这里,我的思路是在电子表中,以通讯录人名为y以日期为x,用"#"标记某人某天有过签到到岗。
先将通讯录中所有人名全部保存至记事本“name.txt”中,读取后保存至列表中
1 def get_name(filename): 2 names = [] 3 with open(filename,'r') as f: 4 for name in f.read().split(): 5 names.append(name) 6 return names
我们需要签到机数据所涉及的所有日期,我这里是先将卡机数据中的日期提取出其中的最小日期和最大日期,随后补全这两个日期之间所有的日期
1 d_min = datetime.datetime.strptime('3000-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') 2 d_max = datetime.datetime.strptime('1900-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') 3 for i in infor_list: 4 d = datetime.datetime.strptime(i[0],'%Y-%m-%d %H:%M:%S') 5 if d > d_max: 6 d_max = d 7 if d < d_min: 8 d_min = d 9 day = datetime.timedelta(days=1) 10 date_list = [] 11 d_temp = d_min 12 while d_temp <= d_max: 13 date_list.append(d_temp) 14 d_temp += day
其实这里也可以先建立一个空列表,遍历所有的日期数据,数据中的日期凡是没存在于列表的添加至该列表。遍历结束后对这个列表进行一下排序就可以了。
1 path = u"考勤结果表%s至%s.xls".encode('GBK') % (d_min.strftime('%Y%m%d'),d_max.strftime('%Y%m%d')) 2 rb = xlwt.Workbook() 3 sheet = rb.add_sheet(u'考勤结果',cell_overwrite_ok=True) 4 5 for k in range(len(date_list)): 6 sheet.write(0,k+1,date_list[k].strftime('%Y-%m-%d')) 7 8 for m in range(len(name_list)): 9 sheet.write(m+1,0,name_list[m].decode('GBK')) 10 for n in range(len(date_list)): 11 for l in range(len(infor_list)): 12 if name_list[m]==infor_list[l][2] and date_list[n].strftime('%Y-%m-%d') == datetime.datetime.strptime(infor_list[l][0],'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d'): 13 sheet.write(m+1,n+1,'#####') 14 rb.save(path)
使用电子表来展现人员考勤情况稍微有些麻烦(代码如上),这里连续使用了3层的循环嵌套,结合着上面的一个循环体,就相当于一开始画好了x轴y轴随后挨着单元格判定卡机数据中是否有该人该天的签到记录。(后来考虑到先将卡机数据按人名将该人所有签到信息保存至字典,随后再往电子表中保存,这样代码量会有所简化,而且一天的四次签到情况都可以得到反映,这将在随后更新)
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 ''' 4 Created on 2018年7月4日 5 6 @author: jinfeng 7 ''' 8 9 import re 10 import datetime 11 import xlwt 12 13 14 def get_name(filename): 15 names = [] 16 with open(filename,'r') as f: 17 for name in f.read().split(): 18 names.append(name) 19 return names 20 21 def get_record(filename): 22 with open(filename,'r') as f: 23 content = f.read() 24 infor_list = re.findall(r'time="(.+?)" id="(.+?)" name="(.+?)"',content) 25 return infor_list 26 27 def result(infor_list,name_list): 28 d_min = datetime.datetime.strptime('3000-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') 29 d_max = datetime.datetime.strptime('1900-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') 30 for i in infor_list: 31 d = datetime.datetime.strptime(i[0],'%Y-%m-%d %H:%M:%S') 32 if d > d_max: 33 d_max = d 34 if d < d_min: 35 d_min = d 36 day = datetime.timedelta(days=1) 37 date_list = [] 38 d_temp = d_min 39 while d_temp <= d_max: 40 date_list.append(d_temp) 41 d_temp += day 42 path = u"考勤结果表%s至%s.xls".encode('GBK') % (d_min.strftime('%Y%m%d'),d_max.strftime('%Y%m%d')) 43 rb = xlwt.Workbook() 44 sheet = rb.add_sheet(u'考勤结果',cell_overwrite_ok=True) 45 46 for k in range(len(date_list)): 47 sheet.write(0,k+1,date_list[k].strftime('%Y-%m-%d')) 48 49 for m in range(len(name_list)): 50 sheet.write(m+1,0,name_list[m].decode('GBK')) 51 for n in range(len(date_list)): 52 for l in range(len(infor_list)): 53 if name_list[m]==infor_list[l][2] and date_list[n].strftime('%Y-%m-%d') == datetime.datetime.strptime(infor_list[l][0],'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d'): 54 sheet.write(m+1,n+1,'#####') 55 rb.save(path) 56 print "Complete!" 57 58 59 60 def main(): 61 name_list = get_name('name.txt') 62 list_infor1 = get_record('TIME182.TXT') 63 result(list_infor1,name_list) 64 65 if __name__ == '__main__': 66 main() 67
运行后最终的结果会保存在一个以卡机数据最小日期与最大日期命名的电子表中,效果如下:
人员的考勤情况看着还算比较直观,但缺点就是一天的四次签到情况无法显示。