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


中控SDK包: x32地址 x64地址

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


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


excel 用了 xlsxwriter 这个功能不错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/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.image  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  =  'test@163.com'  
     password  =  '123123'  
     
     msg  =  MIMEMultipart()  
     msg[ 'Subject' =  'Check_In %s'  %  today.strftime( "%Y-%m-%d" )   
     msg[ 'From' =  "test@163.com"
     msg[ 'To' =  "hr@163.com"
     
# attchment
     if  len (filename) >  0 :
         for  in  filename:
             att  =  MIMEText( open (i,  'rb' ).read(),  'base64' 'gb2312' )  
             att[ "Content-Type" =  'application/octet-stream'  
             att[ "Content-Disposition" =  'attachment; filename="%s"'  %  i.split( '\\' )[ - 1 ]
             msg.attach(att)  
 
# attchment picture
     if  len (picname) >  0  and  content_html ! =  '':
         for  in  range ( 0 , len (picname)):
             #content_html = '<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:image%s"><br>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' '<image%s>'  %  (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  in  range ( 8 , 0 , - 1 ):
     dayNum  =  (today  -  datetime.timedelta(days = i)).strftime( "%Y-%m-%d" )
     =  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
         + =  1
         if  = =  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" ))