爬取班级魔方未体温填报并且发送邮箱
前言
作为某大学的团支书,负责体温填报,每日每个时间段地提醒,有亿点点疲倦了。想写个爬虫来帮我完成,虽然之前写过一个爬虫来帮我每天填报。可那是直接用了别人的学生端登陆,可后台是老师端,这两者有点不一样。而且我本身的Python几乎0基础,主要学习的语言是C/C++和JAVA。但是我偶然看到一个selenium的技术,这玩意就是模拟点击,也可以算是半爬虫吧。但是本次用的就是这玩意。
功能和特性
- 可以由程序无障碍登陆班级魔方后台并且进入体温填报后台界面
- 可以获取Excel的学生的学号和邮箱
- 判断时间点,然后根据时间点判断该同学是否填报该时间段的体温
- 如果未填,则发送邮箱督促其填报。
编写代码过程的坎坷
1. 从Excel中获取数据
Excel表格如图

def read():
wb = openpyxl.load_workbook('./xl.xlsx')
sheet = wb['Sheet1']
active_sheet = wb.active
for i in range(2, 38):
studentId = active_sheet.cell(row=i, column=1).value
studentName = active_sheet.cell(row=i, column=2).value
studentPost = active_sheet.cell(row=i, column=3).value
str(studentId)
str(studentPost)
str(studentName)
arr = {"studentId": studentId, "studentName": studentName, "studentPost": studentPost}
readlists.append(arr)
这里是从用了openpyxl模块,然后从excel中第2行遍历到第37行,取出每一个数据存到一个arr字典里面,然后把每一个字典存到列表里面。
2.模拟点击获取后台数据,然后将从excel获取到字典进行合并
2.1 模拟点击页面
这里先到班级魔方的教师登陆界面,然后用selenium用xpath模拟点击到体温填报界面,并且获取到界面。
易错点:这里因为页面数据较多,需要先sleep一定时间,要不然数据获取不到。
web = Chrome()
web.get("http://banjimofang.com/teacher/login?ref=%2Fteacher")
web.find_element_by_xpath('/html/body/div/div/div/form/div[3]/div[1]/input').send_keys("账号")
web.find_element_by_xpath('/html/body/div/div/div/form/div[3]/div[2]/input').send_keys("密码")
web.find_element_by_xpath('/html/body/div/div/div/form/div[3]/div[4]/button').click()
web.find_element_by_xpath('//*[@id="mainarea"]/div[3]/div[1]/a/div/h5').click()
web.find_element_by_xpath('/html/body/div/div[2]/div/div/div[7]/div[2]/div/div[1]/a/div[1]').click()
web.find_element_by_xpath('/html/body/div/div[2]/div/div/div[8]/a/div[1]/i').click()
web.switch_to.window(web.window_handles[-1])
time.sleep(5)
tr_list = web.find_elements_by_xpath('//*[@id="tmptablebody"]/tr')
2.2 获取班上的人并且合并成字典
这里是先获取到每一个小列表,然后提取数据,再匹配上面获取到的邮箱,将其整合成一个字典。再将其加入列表。
这样的字典就是
arr = {"studentId": studentId, "studentName": studentName, "studentPost": tmpstudentpost, "tem1": tem1, "tem2": tem2, "tem3": tem3}
包含学号,姓名,邮箱,以及早中晚的体温。
易错点:studentID比较注意类型,我本人因为这个改了一个晚上,一直把string == int进行比较。
for tr in tr_list:
q = tr.find_element_by_xpath("./td[3]").text
if q == "班级":
studentId = tr.find_element_by_xpath("./td[2]").text
studentName = tr.find_element_by_xpath("./td[1]").text
tem1 = tr.find_element_by_xpath("./td[4]").text
tem2 = tr.find_element_by_xpath("./td[5]").text
tem3 = tr.find_element_by_xpath("./td[6]").text
tmpstudentpost = "1"
# studentId 是str
str(studentId)
#print(type(studentId))
for i in readlists:
#print(i["studentId"])
#print(type(i["studentId"]))
if str(i["studentId"]) == str(studentId):
tmpstudentpost = i["studentPost"]
break
arr = {"studentId": studentId, "studentName": studentName, "studentPost": tmpstudentpost, "tem1": tem1, "tem2": tem2, "tem3": tem3}
lists.append(arr)
3.判断时间点然后发送邮箱
3.1 获取当前时间并且返回状态码
这里就是判断时间点了,我这边是早上 0 - 11, 11-16,17-22。对应的状态码分别是1 2 3。
小难点:获取时间
def whichtime():
start_time1 = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '0:00', '%Y-%m-%d%H:%M')
end_time1 = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '11:00', '%Y-%m-%d%H:%M')
start_time2 = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '11:00', '%Y-%m-%d%H:%M')
end_time2 = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '16:00', '%Y-%m-%d%H:%M')
start_time3 = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '17:00', '%Y-%m-%d%H:%M')
end_time3 = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '22:00', '%Y-%m-%d%H:%M')
now_time = datetime.datetime.now()
if start_time1 < now_time < end_time1:
return 1
elif start_time2 < now_time < end_time2:
return 2
else:
return 3
3.2匹配时间判断是否已经体温填报
这里没填报的体温是“0.0”这也方便我们进行比较,根据返回的状态码判断需要比较的是什么时候的体温。
易错点:连续发多封邮箱会导致一些问题,所以尽量等大部分人填完再进行发邮箱。
def work():
for i in lists:
nowtimestatus = whichtime()
if nowtimestatus == 1:
if str(i["tem1"]) == "0.0":
receivers = str(i["studentPost"])
send_msg_success(receivers)
time.sleep(2)
print(i["studentId"], nowtimestatus, receivers)
elif nowtimestatus == 2:
if str(i["tem2"]) == "0.0":
receivers = str(i["studentPost"])
send_msg_success(receivers)
time.sleep(2)
print(i["studentId"], nowtimestatus, receivers)
else:
if str(i["tem3"]) == "0.0":
receivers = str(i["studentPost"])
send_msg_success(receivers)
time.sleep(2)
print(i["studentId"], nowtimestatus, receivers)
后言
其实做出来后并没有想象中那么有效。很多同学QQ并没有开启QQ邮箱及时通知。而且程序也无法放到云函数或者其他地方运行。或者说是我不会。但是做这样一个项目,其实加深了我对知识点的理解。
下面附上几张我的痛苦面具吧。这也就是Python小白的无奈吧。





浙公网安备 33010602011771号