笔者学校打卡制度已经实施一年多,然而每天依然有人忘记打卡,笔者也已厌倦了每天重复的机械化操作。为了防止忘记打卡,简化流程,笔者制作了一个简易的自动打卡器,顺便熟悉selenium库和pyqt5库。

实现原理很简单,用python的selenium库模拟用户登录网站并打卡。至于设置开机自启动,只需将程序放到启动文件夹即可。因为笔者最终将程序封装成软件并发给其他人用的,所以用到shutil库和os库的一些函数,将cd到主程序的bat文件自动复制到用户电脑的启动文件夹。最后用pyqt5写一个简单的UI就行啦!至于软件封装,则是用pyinstaller将py文件转化为exe文件。

需要注意的是,selenium库需要本地安装浏览器,所以笔者将浏览器一同集成了,导致软件最终体积很大。不过现在的电脑也不在乎这点大小。

具体代码见下。

打卡模块function.py

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
from selenium import webdriver
from time import sleep
from time import localtime
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from PyQt5.QtWidgets import QApplication, QDialog
from sys import exit,argv
from os import system
import Error,Error2
def report(u,p,t):
if localtime().tm_hour>15:
exit()
option = webdriver.ChromeOptions()
option.binary_location = r'chrome.exe'
browser = webdriver.Chrome('chromedriver.exe')
browser.get('http://ehall.seu.edu.cn/qljfwapp2/sys/lwReportEpidemicSeu/*default/index.do#/dailyReport')
sleep(1)
namebar = browser.find_element_by_xpath("//*[@id='username']")
namebar.send_keys(u)
passwordbar = browser.find_element_by_xpath("//*[@id='password']")
passwordbar.send_keys(p)
passwordbar.send_keys(Keys.ENTER)
sleep(6)
try:
try:
button = browser.find_element_by_xpath("//*[@id='app']/div/div[1]/button[1]")
button.click()
except:
return 2
sleep(3)
temp = browser.find_element_by_xpath("//*[@id='app']/div/div/div[2]/div/div[4]/div/div[2]/div[1]/div/a/div[2]/div[2]/input")
temp.send_keys(t)
button2 = browser.find_element_by_xpath("//*[@id='app']/div/div/div[4]/button")
button2.click()
sleep(1)
button3 = browser.find_element_by_xpath("/html/body/div[3]/div/div[3]/button[2]")
button3.click()
sleep(1)
browser.close()
return 1
except:
return 0

if __name__=='__main__':
p=open('data2.txt','r')
if p.read()==localtime().tm_yday:
system("taskkill /f /im cmd.exe")
try:
f = open("data.txt", 'r')
data = f.read().splitlines()
u=data[0]
p=data[1]
t=data[2]
if report(u,p,t)==False:
app = QApplication(argv)
dialog=QDialog()
ui = Error.Ui_Error()
ui.setupUi(dialog)
dialog.show()
else:
system("taskkill /f /im cmd.exe")
except:
app = QApplication(argv)
dialog=QDialog()
ui = Error2.Ui_Error()
ui.setupUi(dialog)
dialog.show()

主函数main.py

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
from __future__ import print_function
import sys,ctypes
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
import AutoReport,dialog1,dialog2
from shutil import copy
from function import report
from time import localtime
import os
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False

def creatAutoStart():
f=open("AutoStart.txt",'w')
path=os.getcwd()
dist=path[0:2]
pos=path[2:]
f.write(dist+'\n'+'cd '+pos+'\n'+'start function.exe')
f.close()
try:
os.rename('AutoStart.txt','AutoStart.bat')
except:
os.unlink('AutoStart.bat')
os.rename('AutoStart.txt','AutoStart.bat')
pass
copy('AutoStart.bat',"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp")

def deleteAutoStart():
try:
os.unlink("C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\AutoStart.bat")
except:
pass


def save():
f = open("data.txt", 'w')
f.write(ui.lineEdit.text() + '\n')
f.write(ui.lineEdit_2.text() + '\n')
f.write(ui.lineEdit_3.text() + '\n')
judge=ui.checkBox.isChecked()
f.write(str(judge))
f.close()
if judge:
creatAutoStart()

else:
deleteAutoStart()
ui.showdialog1()




def submit():
f=open('data2.txt','r')
if f.read()!=str(localtime().tm_yday):
u=ui.lineEdit.text()
p=ui.lineEdit_2.text()
t=ui.lineEdit_3.text()
k=report(u,p,t)
f.close()
if k==1:
f=open('data2.txt','w')
f.write(localtime().tm_yday)
ui.showdialog2()
if k==2:
ui.showdialog3()
f=open('data2.txt','w')
f.write(localtime().tm_yday)
if k==0:
ui.showdialog4()
else:
ui.showdialog3()

if __name__ == '__main__':
if is_admin():
app = QApplication(sys.argv)
MainWindow = QMainWindow()
ui = AutoReport.Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
try:
f = open("data.txt", 'r')
data = f.read().splitlines()
ui.lineEdit.setText(data[0])
ui.lineEdit_2.setText(data[1])
ui.lineEdit_3.setText(data[2])
if (data[3] == 'True'):
ui.checkBox.setChecked(True)
except:
f = open("data.txt", 'w')
f.close()
ui.pushButton.clicked.connect(save)
ui.pushButton_2.clicked.connect(submit)
sys.exit(app.exec_())
else:
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
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
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(612, 308)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(240, 20, 141, 31))
self.label.setScaledContents(False)
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(140, 80, 191, 21))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setGeometry(QtCore.QRect(140, 130, 191, 21))
self.lineEdit_2.setObjectName("lineEdit_2")
self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_3.setGeometry(QtCore.QRect(140, 180, 51, 21))
self.lineEdit_3.setObjectName("lineEdit_3")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(60, 80, 72, 15))
self.label_2.setObjectName("label_2")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(90, 130, 72, 15))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(60, 180, 72, 15))
self.label_4.setObjectName("label_4")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(140, 250, 91, 31))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(420, 120, 131, 61))
self.pushButton_2.setObjectName("pushButton_2")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(230, 170, 101, 41))
self.checkBox.setObjectName("checkBox")
self.checkBox.raise_()
self.label.raise_()
self.lineEdit.raise_()
self.lineEdit_2.raise_()
self.lineEdit_3.raise_()
self.label_2.raise_()
self.label_3.raise_()
self.label_4.raise_()
self.pushButton.raise_()
self.pushButton_2.raise_()
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)

self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "AutoReport"))
self.label.setText(_translate("MainWindow", "健康申报自动打卡器"))
self.label_2.setText(_translate("MainWindow", "一卡通号:"))
self.label_3.setText(_translate("MainWindow", "密码:"))
self.label_4.setText(_translate("MainWindow", "上报温度:"))
self.pushButton.setText(_translate("MainWindow", "保存"))
self.pushButton_2.setText(_translate("MainWindow", "上报"))
self.checkBox.setText(_translate("MainWindow", "开机自启动"))

def showdialog1(self):
dialog = QtWidgets.QDialog()
dialog.resize(200,100)
dialog.setWindowTitle("Dialog")
dialog.lb = QtWidgets.QLabel('保存成功',dialog)
dialog.lb.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
dialog.exec_()

def showdialog2(self):
dialog = QtWidgets.QDialog()
dialog.resize(200,100)
dialog.setWindowTitle("Dialog")
dialog.lb = QtWidgets.QLabel('上报成功',dialog)
dialog.lb.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
dialog.exec_()

def showdialog3(self):
dialog = QtWidgets.QDialog()
dialog.resize(200,100)
dialog.setWindowTitle("Dialog")
dialog.lb = QtWidgets.QLabel('今日已上报!',dialog)
dialog.lb.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
dialog.exec_()

def showdialog4(self):
dialog = QtWidgets.QDialog()
dialog.resize(200,100)
dialog.setWindowTitle("Dialog")
dialog.lb = QtWidgets.QLabel('发生未知错误!',dialog)
dialog.lb.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
dialog.exec_()

错误提示框Error.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Error(object):
def setupUi(self, Error):
Error.setObjectName("Error")
Error.resize(285, 93)
self.label = QtWidgets.QLabel(Error)
self.label.setGeometry(QtCore.QRect(100, 30, 101, 16))
self.label.setObjectName("label")

self.retranslateUi(Error)
QtCore.QMetaObject.connectSlotsByName(Error)

def retranslateUi(self, Error):
_translate = QtCore.QCoreApplication.translate
Error.setWindowTitle(_translate("Error", "Dialog"))
self.label.setText(_translate("Error", "出现未知错误!"))

错误提示框Error2.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Error(object):
def setupUi(self, Error):
Error.setObjectName("Error")
Error.resize(285, 93)
self.label = QtWidgets.QLabel(Error)
self.label.setGeometry(QtCore.QRect(100, 30, 101, 16))
self.label.setObjectName("label")

self.retranslateUi(Error)
QtCore.QMetaObject.connectSlotsByName(Error)

def retranslateUi(self, Error):
_translate = QtCore.QCoreApplication.translate
Error.setWindowTitle(_translate("Error", "Dialog"))
self.label.setText(_translate("Error", "用户数据缺失!"))

软件自取:

提取码8848