用python连接中控考勤机。 下载并分析数据,把结果邮件给人事。
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
i
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
i
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
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"
))
|
本文转自 nonono11 51CTO博客,原文链接:http://blog.51cto.com/abian/1627674,如需转载请自行联系原作者