基于阿里云服务器的我在校园班委自动管理系统

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
云服务器ECS,u1 2核4GB 1个月
简介: 利用python构造程序放置于阿里云服务器,实现我在校园固定时间点,自动通过邮箱提醒未完成日检日报、签到的同学完成打卡,以及程序的实现过程。

本文仅用于学习用途,转载请注明出处

关键词

python、fiddler抓包、服务器、我在校园、HTTP

0-引言

因学校要求,班委需提醒未完成打卡同学打卡,否则扣除德育分,影响德育成绩。所以为实现班委我在校园的自动化管理,尝试使用python编写一个爬虫程序挂靠在服务器运行,实现每天的自动提醒管理。
经前期搜索,互联网上的我在校园爬虫未涉及班委的自动化管理,且仅仅通过token或者JWSESSION实现登录,时效性不好且操作麻烦。例如github上面的我在校园自动签到程序,通过token值实现签到,但现已经停止维护,且token值登录已经被我在校园登录给禁止。csdn和博客园的部分文章仅仅涉及通过抓包获取JWSESSION实现登录签到,但是有效期不长。

1-总流程图

总流程图.jpg

2.1-抓包解析过程

部分关键信息已经打码
打开fiddler和我在校园小程序,登录,抓取到登录信息如下
登录表头1.png
登录表头2.png
由其中发现,我在校园登录是通过url中的符号 ? 来实现传值的,由于登录的时候没有后面的openid等值,猜测传入账号和密码就可以实现登录。
经检验,猜测正确。
按照正常流程进入班级管理界面,依次进入日渐日报管理和班级签到管理,而后检查抓包信息
我在校园班级管理界面
我在校园班级管理界面.jpg
日检日报界面
日检日报.png
同理进入签到页面检查,发现出入的参数有一个id
签到图1.png
经检查,在上一级页面的respond的中,发现了该天的id,图略

2.2-构建爬虫程序

代码有注释,变量均采用英文命名,可直接阅读

#!/usr/bin/env Python
# coding=utf-8
import requests
import json
import time


class auto_tips:
    def __init__(self, username, password):
        self.not_heat_names_list = []
        self.not_sign_names_list = []
        # 保留登录信息
        self.session = requests.session()
        self.cookies = None

        # 登入界面的post信息
        self.login_url = 'https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username'
        self.login_data = {
            'username': username,
            'password': password
        }
        self.login_headers = {
            'Host': 'gw.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'Content-Length': '2',
            'Accept': 'application/json, text/plain, */*',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'Content-Type': 'application/json;charset=UTF-8',
            'Sec-Fetch-Site': 'same-origin',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Dest': 'empty',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'en-us,en'
        }
        # 班级日检日报的信息
        self.getHeatUsers_url = 'https://student.wozaixiaoyuan.com/heat/getHeatUsers.json'
        self.getHeatUsers_headers = {
            'Host': 'student.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'content-type': 'application/x-www-form-urlencoded',
            'Accept-Encoding': 'gzip, deflate, br'
        }
        self.getHeatUsers_data = {'seq': '1', 'date': str(time.strftime("%Y%m%d")), 'type': '0'}  # 测试用的,后边程序会更改
        # 校区签到的列表
        self.getList_url = 'https://student.wozaixiaoyuan.com/gradeManage/sign/getList.json'
        self.getList_headers = {
            'Host': 'student.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'content-type': 'application/x-www-form-urlencoded',
            'Accept-Encoding': 'gzip, deflate, br'
        }
        self.getList_date = {
            'keyword': '',
            'page': '1'
        }
        # 校区签到的班级成员情况
        self.getSignResult_url = 'https://student.wozaixiaoyuan.com/gradeManage/sign/getSignResult.json'
        self.getSignResult_headers = {
            'Host': 'student.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'content-type': 'application/x-www-form-urlencoded',
            'Accept-Encoding': 'gzip, deflate, br'
        }
        self.getSignResult_data = {
            'id': ''
        }

    def login(self):  # 登入账号
        self.login_url = self.login_url + "?username=" + str(self.login_data['username']) + "&password=" + str(
            self.login_data['password'])  # 通过 url 的 '?' 方法写入参数  # 更新url
        res = self.session.post(url=self.login_url, headers=self.login_headers, data='{}')
        try:
            if json.loads(res.text)['code'] == 0:
                self.session.cookies.set('JWSESSION', res.headers['JWSESSION'])  # 更新JWSESSION值
                print('{}\t登录成功'.format(time.strftime("%H:%M:%S")))
            else:
                print('{}\t登录失败:{}'.format(time.strftime("%H:%M:%S"), json.loads(res.text)['message']))  # 输出登录错误的错误原因
        except:
            print('{}\t登录错误'.format(time.strftime("%H:%M:%S")))

    def get_HeatUsers(self):
        try:
            res = self.session.post(url=self.getHeatUsers_url, headers=self.getHeatUsers_headers,
                                    data=self.getHeatUsers_data)
            if json.loads(res.text)['code'] == 0:  # 检查是否请求成功且正确
                # print('{}\t成功获得班级成员日检日报信息'.format(time.strftime("%H:%M:%S")))
                data = json.loads(res.text)['data']   # 观察是否有不晨检的同学
                if len(data) != 0:
                    for inf in data:  # 如果有,则更新不晨检列表
                        name = inf['name']
                        self.not_heat_names_list.append(name)
                    print('{}\t未完成日检日报的班级成员为{}'.format(time.strftime("%H:%M:%S"), self.not_heat_names_list))
                else:
                    print('{}\t班级成员全部完成日检日报'.format(time.strftime("%H:%M:%S")))

            else:
                print('{}\t获得班级成员日检日报信息失败:{}'.format(time.strftime("%H:%M:%S"), json.loads(res.text)['message']))  # 输出登录错误的错误原因
        except:
            print('{}\t获得班级成员日检日报信息失败'.format(time.strftime("%H:%M:%S")))

    def get_SignResult(self):
        # 获取当天的签到 id 值
        try:
            res = self.session.post(url=self.getList_url, headers=self.getList_headers,
                                    data=self.getList_date)
            if json.loads(res.text)['data'][0]['end'].split(' ')[0] == time.strftime("%Y-%m-%d"):  # 判断第一个签到是不是当天的签到
                self.getSignResult_data['id'] = json.loads(res.text)['data'][0]['id']  # 如果判断成功,则更新 查询签到的id
                res = self.session.post(url=self.getSignResult_url, headers=self.getSignResult_headers,  # 查询签到
                                        data=self.getSignResult_data)
                data = json.loads(res.text)['data']
                if len(data['notSign']) != 0:  # 判断是否有成员不签到
                    for inf in data['notSign']:
                        name = inf['name']
                        self.not_sign_names_list.append(name)
                    print('{}\t未完成签到的班级成员为{}'.format(time.strftime("%H:%M:%S"), self.not_sign_names_list))
                else:
                    print('{}\t班级成员全部完成签到'.format(time.strftime("%H:%M:%S")))
        except:
            print('{}\t获得班级成员签到信息失败'.format(time.strftime("%H:%M:%S")))


if __name__ == '__main__':
    obj = auto_tips('账号名', '密码')
    obj.login()
    obj.get_HeatUsers()
    obj.get_SignResult()

2.3-构建邮件提醒程序

同上,可直接阅读

import smtplib
from email.mime.text import MIMEText
# email 用于构建邮件内容
from email.header import Header


class email_obj:
    def __init__(self, to_addr=None, email_Subject=None, email_content=None):
        data_inf_path = r'系统日志\email_data.txt'   # 邮箱信息的存储路径
        with open(data_inf_path, 'r+', encoding='UTF-8') as f:
            data_inf = eval(f.read())  # 读取邮箱信息
            f.close()
        self.from_addr = data_inf['发信邮箱']  # 发信邮箱
        self.password = data_inf['邮箱授权码']  # 发信邮箱的授权码
        self.smtp_server = data_inf['发信服务器']  # 发信服务器的域名
        self.to_addr = to_addr  # 收信邮箱
        self.email_Subject = email_Subject  # 邮件标题
        self.email_content = email_content  # 邮件内容

        # 开启发信服务,这里使用的是加密传输
        self.server = smtplib.SMTP_SSL(host=self.smtp_server)  # POP3/SMTP 协议的发送邮件服务器
        self.server.connect(self.smtp_server, 465)  # 使用SSL,端口号465
        # 登录发信邮箱
        self.server.login(self.from_addr, self.password)

    def change_email_inf_to(self, to_addr, email_Subject, email_content):
        self.to_addr = to_addr  # 收信邮箱
        self.email_Subject = email_Subject  # 邮件标题
        self.email_content = email_content  # 邮件内容

    def send(self):
        # 邮箱正文内容,第一个参数为内容,第二个参数为格式(plain 为纯文本),第三个参数为编码
        msg = MIMEText(self.email_content, 'plain', 'utf-8')

        # 邮件头信息
        msg['From'] = Header(self.from_addr)
        msg['To'] = Header(self.to_addr)
        msg['Subject'] = Header(self.email_Subject)

        # 发送邮件
        self.server.sendmail(self.from_addr, self.to_addr, msg.as_string())

    def close(self):
        # 关闭服务器
        self.server.quit()


if __name__ == '__main__':
    to_addr = 'xxx@xx.xxx'
    email_Subject = 'send by python'
    email_content = 'python test'
    obj = email_obj(to_addr, email_Subject, email_content)
    obj.send()

定时触发程序

#!/usr/bin/env Python
# coding=utf-8
import tips
import send_email
import pandas as pd
import time


def heat_tip(file):  # 晨检提醒
    obj = tips.auto_tips('真实账号', '真实密码')
    obj.login()
    obj.get_HeatUsers()
    name_list = obj.not_heat_names_list
    if len(name_list) != 0:
        user_email = send_email.email_obj()  # 登录邮箱
        for i in range(len(name_list)):  # 依次编辑文件
            name_i = name_list[i]
            for j in range(len(file)):
                name_j = file.iloc[j, 0]
                if name_i == name_j:
                    qq = file.iloc[j, 1]
                    qq_email = qq + '@qq.com'
                    email_Subject = '日检日报提醒'
                    email_content = '赶紧晨检了,现在已经是{}了'.format(time.strftime("%H:%M:%S"))
                    user_email.change_email_inf_to(to_addr=qq_email, email_Subject=email_Subject,
                                                      email_content=email_content)
                    user_email.send()
        user_email.close()  # 退出邮箱


def sign_tip(file):  # 签到提醒
    obj = tips.auto_tips('真实账号', '真实密码')
    obj.login()
    obj.get_SignResult()
    name_list = obj.not_sign_names_list
    if len(name_list) != 0:
        user_email = send_email.email_obj()  # 登录邮箱
        for i in range(len(name_list)):  # 依次编辑文件
            name_i = name_list[i]
            for j in range(len(file)):
                name_j = file.iloc[j, 0]
                if name_i == name_j:
                    qq = file.iloc[j, 1]
                    qq_email = qq + '@qq.com'
                    email_Subject = '签到提醒'
                    email_content = '赶紧晨检了,现在已经是{}了'.format(time.strftime("%H:%M:%S"))
                    user_email.change_email_inf_to(to_addr=qq_email, email_Subject=email_Subject,
                                                   email_content=email_content)
                    user_email.send()
        user_email.close()  # 退出邮箱


def seconds(now_time):  # 把时间转化为秒
    hour = int(now_time.split(':')[0])
    minute = int(now_time.split(':')[1])
    second = int(now_time.split(':')[2])
    now_seconds = hour * 60 * 60 + minute * 60 + second
    return now_seconds


def get_sleep_time(now_time, to_time):  # 获得程序睡眠时间
    sleep_time = seconds(to_time) - seconds(now_time)
    return sleep_time  # 单位是s


def auto_tips():
    file = pd.read_excel(r'用户信息\班级成员信息.xlsx')
    print('开始运行')
    # 晨检提醒时间
    heat_tip_time_1 = '11:00:00'
    heat_tip_time_2 = '11:30:00'
    heat_tip_time_3 = '11:50:00'
    # 签到提醒时间
    sign_tip_time_1 = '22:05:00'
    sign_tip_time_2 = '22:15:00'
    sign_tip_time_3 = '22:25:00'
    tips_time_list = [heat_tip_time_1, heat_tip_time_2, heat_tip_time_3, sign_tip_time_1, sign_tip_time_2,
                      sign_tip_time_3]  # 按顺序放好
    ####
    while True:
        flag = 0  # 判断当前时间是否在提醒时间前
        tip_name = None  # 提醒的事件名称
        sleep_time = None  # 睡眠时间
        for i in range(len(tips_time_list)):  # 判断当前时间
            tip_time = tips_time_list[i]
            now_time = time.strftime("%H:%M:%S")  # 时:分:秒
            if seconds(now_time) < seconds(tip_time): 
                sleep_time = get_sleep_time(now_time=now_time, to_time=tip_time)
                if i <= 2:
                    tip_name = '晨检'
                else:
                    tip_name = '签到'
                flag = 1
                break
        if flag == 0:
            now_time = time.strftime("%H:%M:%S")  # 时:分:秒
            sleep_time = get_sleep_time(now_time=now_time, to_time='24:00:00') + get_sleep_time(now_time='00:00:00',
                                                                                                to_time=tips_time_list[0])
            tip_name = '晨检'
        print('{}\t即将休眠{}秒'.format(time.strftime("%H:%M:%S"), sleep_time))
        time.sleep(sleep_time)
        if tip_name == '晨检':
            heat_tip(file)
        elif tip_name == '签到':
            sign_tip(file)
        print('{}\t提醒信息已经发送'.format(time.strftime("%H:%M:%S")))


if __name__ == '__main__':
    # print(seconds('07:10:12'))
    auto_tips()

2.4-配置文件

文件如图配置
程序配置.png
文件信息.jpg

2.5-打包并且配置到服务器上

利用pyinstaller打包auto_tips.py
然后用命令控制符的mstsc命令,连接远程服务器,把整个文件夹上传到服务器运行。

3-过程碰到的问题

3.1-抓取不到登录界面

问题描述打开微信小程序,进入我在校园后,只获得了get信息,然后就自动转接微信授权登录,无法抓取到post信息
解决方法换另一台电脑登录后,再重新返回本电脑登录我在校园,微信授权登录就会失败,然后就可以账号密码登入,抓取到对应的信息

3.2-获取不了邮箱的授权码

问题描述我用的是阿里云购买的域名,解析到腾讯企业邮箱的服务器上,注册了域名邮箱。找不到对应的授权码
解决方法打开腾讯企业邮箱,给对应的邮箱开头SMTP服务,然后进入邮箱,设置中处理就可以了。详细教程网上可以查到

3.3nssm-把exe文件注册成服务

问题描述把exe文件通过nssm程序注册成计算机服务,后台运行服务时候,运行失败
暂未解决

相关实践学习
一小时快速掌握 SQL 语法
本实验带您学习SQL的基础语法,快速入门SQL。
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
Cloud Native 自动驾驶 NoSQL
亚太唯一,阿里云连续4年入选Gartner®云数据库管理系统魔力象限领导者象限
国际市场研究机构Gartner®日前公布2023年度全球《云数据库管理系统魔力象限》报告,阿里云成为亚太区唯一入选该报告“领导者(LEADERS)”象限的科技公司,同时也是唯一一家连续4年入选“领导者”象限的中国企业。
亚太唯一,阿里云连续4年入选Gartner®云数据库管理系统魔力象限领导者象限
|
4月前
|
数据库 数据安全/隐私保护
在阿里云中,访问控制(Resource Access Management,简称RAM)是权限管理系统,主要用于控制账号在阿里云中
在阿里云中,访问控制(Resource Access Management,简称RAM)是权限管理系统,主要用于控制账号在阿里云中
522 3
|
4月前
|
存储 数据采集 运维
构建高效日志管理系统:阿里云产品实践与技术解析
日志管理对于系统运维和故障排查至关重要。本文将详细介绍如何利用阿里云相关产品搭建一个高效、可扩展的日志管理系统。我们将使用Log Service、Elasticsearch、DataHub等阿里云产品,通过代码示例和详细说明,带你一步步完成整个流程。
131 0
|
7月前
阿里云秋季2024届校园招聘已开启,等你来投!
阿里云秋季2024届校园招聘已开启,等你来投!
559 0
阿里云秋季2024届校园招聘正式启动!
阿里云秋季2024届校园招聘已于8月28日正式启动,欢迎投递!
阿里云秋季2024届校园招聘,开启倒计时3天!
阿里云秋季2024届校园招聘将于8月28日正式开启!
|
8月前
|
弹性计算 关系型数据库 MySQL
【ECS生长万物之开源】搭建Moodle课程管理系统
Moodle是一个课程管理系统,采用PHP加MySQL方式运行的自由开源软件。使用Moodle为学生建立网上动态网站,可以根据需要随时调整界面、增减内容。本教程介绍如何使用云市场镜像快速搭建Moodle课程管理系统。
|
10月前
|
Cloud Native 自动驾驶 关系型数据库
阿里云连续3年跻身Gartner全球云数据库管理系统领导者象限
阿里云连续3年跻身Gartner全球云数据库管理系统领导者象限
227 0
|
10月前
|
负载均衡 Shell
服务器集群管理系统SGE使用指南
服务器集群管理系统SGE使用指南
|
数据可视化 前端开发 数据挖掘
电子信息毕业设计VUE+websocket+Echart+服务器的智能农业管理系统
对于我们的传统农业生产方式,对于农田的参数检测、病虫害预警、远程管控等的实时效果能力达不到,对于现在的农作物而言,我们知道,农作物最重要的生长标准环境就是农地里的光照、温湿度、病虫害等等的因素,但是我们现在的传统生产方式是远远达不到要求的
电子信息毕业设计VUE+websocket+Echart+服务器的智能农业管理系统