爬取班级魔方未体温填报并且发送邮箱

元胞珊瑚
• 阅读 531

前言

作为某大学的团支书,负责体温填报,每日每个时间段地提醒,有亿点点疲倦了。想写个爬虫来帮我完成,虽然之前写过一个爬虫来帮我每天填报。可那是直接用了别人的学生端登陆,可后台是老师端,这两者有点不一样。而且我本身的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小白的无奈吧。

爬取班级魔方未体温填报并且发送邮箱

爬取班级魔方未体温填报并且发送邮箱

爬取班级魔方未体温填报并且发送邮箱

爬取班级魔方未体温填报并且发送邮箱

源码链接

源码

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
4年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Stella981 Stella981
4年前
Scapy 从入门到放弃
0x00前言最近闲的没事,抽空了解下地表最强的嗅探和收发包的工具:scapy。scapy是一个python模块,使用简单,并且能灵活地构造各种数据包,是进行网络安全审计的好帮手。0x01安装因为2020年python官方便不再支持python2,所以使用python3安装。!(https://oscimg.oschina.net/os
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
4年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Wesley13 Wesley13
4年前
Valine评论系统邮件提醒
这几天想到,别人给我发的评论,我还要到后台去看,实在是太麻烦了,于是发现了一个好项目valineadmin可以帮我发送邮件评论提醒,这样我就可以实时收到别人给我发的评论。!image(https://oscimg.oschina.net/oscnet/5940a6f5b07c26046b2c2fa0e9b40e56249.png)<btnce