用python连接中控考勤机。 下载并分析数据,把结果邮件给人事。


中控SDK包: x32地址 x64地址

SDK包建议用32位的,在win7 64位系统上用64位开发包不行,用32可以。


python还要pywin32 注意版本,我这用的 32位的python 2.7 然后下的这个pywin32


excel 用了 xlsxwriter 这个功能不错

#!/usr/bin/env python
#_*_ coding:gbk _*_

import win32com.client
import datetime
import xlsxwriter
import sys
import smtplib
from email.mime.multipart import MIMEMultipart  
from email.mime.text import MIMEText  
from email.mime.p_w_picpath import MIMEImage  

non = {21:"niu.niu", }  #非研发人员
no_checkin = [1,34,35,36,23,40]  #不计考勤人员

def send_mail(filename=[], picname=[], content_txt='', content_html=''): 
    smtpserver = 'smtp.163.com'  
    username = '[email protected]'  
    password = '123123'  
    
    msg = MIMEMultipart()  
    msg['Subject'] = 'Check_In %s' % today.strftime("%Y-%m-%d")   
    msg['From'] = "[email protected]"
    msg['To'] = "[email protected]"
    
# attchment
    if len(filename) > 0:
        for i in filename:
            att = MIMEText(open(i, 'rb').read(), 'base64', 'gb2312')  
            att["Content-Type"] = 'application/octet-stream'  
            att["Content-Disposition"] = 'p_w_upload; filename="%s"' % i.split('\\')[-1]
            msg.attach(att)  

# attchment picture
    if len(picname) > 0 and content_html != '':
        for i in range(0,len(picname)):
            #content_html = 'Some HTML text and an p_w_picpath.

good!' % i               msg_content_html = MIMEText(content_html,'html','gb2312')               msg.attach(msg_content_html)                            with open(picname[i], 'rb') as f:                 msgImage = MIMEImage(f.read())                            msgImage.add_header('Content-ID', '' % (i + 1))               msg.attach(msgImage)      # content text         if content_txt != '':         msg_content_txt = MIMEText(content_txt,_subtype='plain',_charset='gb2312')          msg.attach(msg_content_txt) # content html       if content_html != '' and len(picname) == 0:         msg_content_html = MIMEText(content_html,_subtype='html',_charset='gb2312')          msg.attach(msg_content_html)              smtp = smtplib.SMTP()       smtp.connect(smtpserver)       smtp.starttls()       smtp.login(username, password)       smtp.sendmail(msg['From'], msg['To'], msg.as_string())       smtp.quit()       zk = win32com.client.Dispatch('zkemkeeper.ZKEM.1') if not zk.Connect_Net('192.168.1.31', 4370):     print "Connect Error"     sys.exit(1) if len(sys.argv) == 2: #如果以 ./script 2015-11-22 这样的方式运行,可以指定别的星期     today = datetime.datetime.strptime( sys.argv[1] + " 11:22:33", '%Y-%m-%d %H:%M:%S') else:     today = datetime.datetime.now()     zk.SetDeviceTime(1)     #set pc time       if datetime.datetime.now().weekday() != 0:          zk.Disconnect()         sys.exit(1)    zk.ReadAllUserID(1) uid = {} while 1:     exists, idNum, username, other, privilege, enable = zk.GetAllUserInfo(1)     if not exists:         break     else:         if enable:             uid[idNum] = username.split(u'\x00')[0].encode('gbk') checkin,uid_name  = {}, [] if len(sys.argv) == 1:     log = open(today.strftime("D:\\CheckIn\\bak\\%Y-%m-%d.txt"), "w") if zk.ReadGeneralLogData(1):  #read All checkin data     while 1:         exists, machNum, idNum, emachNum, verifyMode, outMode, year, month, day, hour, minute = zk.GetGeneralLogData(1) #2            if year <= today.year:             if 0 < (datetime.date(today.year,today.month,today.day) - datetime.date(year,month,day)).days < 8:                 if len(sys.argv) == 1:                     log.write("%s-%s-%s %02d:%02d %s %s\n" % (year,month,day,hour,minute,uid.get(idNum,"ERROR"),idNum))                    if idNum not in uid:                     continue                 if day not in checkin:                     checkin[day] = {}                    try:                     checkin[day][idNum].append(hour * 60 + minute)                 except:                     checkin[day][idNum] = [hour * 60 + minute]         else:             break if len(sys.argv) == 1:     log.close()             zk.Disconnect() if len(sys.argv) == 1:  #自动运行保存指定位置     workbook = xlsxwriter.Workbook(today.strftime("D:\\CheckIn\\xlsx\\%Y-%m-%d.xlsx")) else:     workbook = xlsxwriter.Workbook(today.strftime("%Y-%m-%d.xlsx")) worksheet = workbook.add_worksheet("WeekAll") worksheet.set_column(0, 0, 10) format1 = workbook.add_format({'bg_color': '#FFC7CE'}) sheet = {} uid_name = sorted(uid.keys()) for i in range(8,0,-1):     dayNum = (today - datetime.timedelta(days=i)).strftime("%Y-%m-%d")     n = 0     if i < 8:         worksheet.write(8-i, n, dayNum)         sheet[8-i] = workbook.add_worksheet(dayNum)         worksheet.write_url(row=8-i,col=0,url="internal:'%s'!A1" % dayNum, string=dayNum, tip=dayNum)         sheet[8-i].write(0,0,"Name")         sheet[8-i].write(0,1,"AM")         sheet[8-i].write(0,2,"PM")         sheet[8-i].write(0,3,"Time")     dayNum = int(dayNum.split('-')[-1])     for col in uid_name:         work_time = 9         if col in no_checkin:  #不需要统计考勤             continue         n += 1         if i == 8:             worksheet.write(8-i, n, uid[col].decode('gbk'))             continue         sheet[8-i].write(n, 0, uid[col].decode('gbk'))         if dayNum not in checkin or col not in checkin[dayNum]:             continue         if len(checkin[dayNum][col]) < 2 and i > 2:             sheet[8-i].write(n, 3, 0, format1)             worksheet.write(8-i, n, 0, format1)             am = checkin[dayNum][col][0]             pm = 0         else:             min_time = am = min(checkin[dayNum][col])             max_time = pm = max(checkin[dayNum][col])             if min_time < 510:   #最早从8:30 计考勤                 min_time = 510             elif col not in non and 570 < min_time <= 600:  #研发9:30后,10:00以前,算两倍。                 if (min_time-570) * 2 <= 30:                     work_time += 0.5                 else:                     work_time += 1                          dayTime = max_time - min_time  #当天工作时间                          if dayTime%60 >= 45:                 dayTime = dayTime//60 + 1             elif 15 <= dayTime%60 < 45:                 dayTime = dayTime//60 + 0.5             else:                 dayTime = dayTime//60                          if (col in non and min_time > 540) and i > 2:  #非研发过 9 点算迟到                 sheet[8-i].write(n, 3, dayTime, format1)                 worksheet.write(8-i, n, dayTime, format1)             elif (col not in non and min_time > 600) and i > 2: #研发过 10 点算迟到                 sheet[8-i].write(n, 3, dayTime, format1)                 worksheet.write(8-i, n, dayTime, format1)                         elif dayTime < work_time and i > 2:  #时间不够未到工作时间                 sheet[8-i].write(n, 3, dayTime, format1)                 worksheet.write(8-i, n, dayTime, format1)                                  else:                 worksheet.write(8-i, n, dayTime)                 sheet[8-i].write(n, 3, dayTime)                                     #添加批注         if pm:             worksheet.write_comment(8-i, n, 'AM  %02d:%02d\nPM  %02d:%02d' % (am//60, am%60,                                         pm//60, pm%60))                sheet[8-i].write(n, 1, '%02d:%02d' % (am//60, am%60))              sheet[8-i].write(n, 2, '%02d:%02d' % (pm//60, pm%60))         else:                                                     if am < 720:                 worksheet.write_comment(8-i, n, 'AM  %02d:%02d' % (am//60, am%60))                  sheet[8-i].write(n, 1, '%02d:%02d' % (am//60, am%60))             else:                 worksheet.write_comment(8-i, n, 'PM  %02d:%02d' % (am//60, am%60))                     sheet[8-i].write(n, 2, '%02d:%02d' % (am//60, am%60))                                         workbook.close() if len(sys.argv) == 1:     send_mail(filename=[today.strftime("D:\\CheckIn\\xlsx\\%Y-%m-%d.xlsx")], content_txt='Check_In %s' % today.strftime("%Y-%m-%d"))