python实现今日校园APP自动签到

序言

起因很简单,由于我校要对学生做疫情相关的信息采集,所以就采用“今日校园”这款APP,要求每个学生在规定时间内进行信息提交,通俗点说就是每日签到,我并不反感这种每日签到的现象,但是我每天都在居住地,每天填写的信息都是一样,每天都重复着相同的动作,难道这不能自动化运行吗?作为一名运维工程师,我认为,这可以从技术层面上去带来便利,毕竟不是每个人都能在中午12点前起床的,特别像我这种昼伏夜出的人。因此,我对“今日校园”APP进行了简单分析,根据分析结果,写了个python脚本,最终部署到Linux云服务器上,实现自动签到。

今日校园APP的分析

抓包软件的选择

抓包软件有很多,像是Fiddler、Wireshark或是Burpsuite,这里可以根据每一位开发者的使用习惯,选择自己最拿手的软件,我这次分析用的是Charles,APP抓包我也是第一次抓,所以还是记录一下,很有价值意义。

攻破SSL加密通信下无法正常抓包的难题

开发者基于信息传输的安全性设计,全程都采用了SSL加密,这使得Charles的抓包不能像普通的WEB网页一样搞,那么必须先在电脑端和手机端安装相对应的SSL证书。

Charles下设置SSL代理

1、Proxy Settings
在这里插入图片描述


设置监听的端口,端口号可随意设置,尽量选择可自由使用的端口号,本次测试我用的是8080端口
在这里插入图片描述



2、SSL Proxying Settings
在这里插入图片描述


启用SSL代理,添加监听规则,其中【*: *】代表监听所有IP地址的所有端口
在这里插入图片描述



3、安装证书
在这里插入图片描述


4、手机端安装证书
在这里插入图片描述


这里会有提示,首先将手机的网络设置,添加手工代理,IP和端口号分别指向下图箭头所示。值得一提的是,现在的安卓系统,由于版本过高,做了相关的代理限制,不再信任外部导入的证书,所以基本搞不了,除非把安全策略给注释掉,相当的麻烦。因此我找了一台iphone,所幸的是,IOS系统中,依旧能自行添加信任。
在这里插入图片描述


分析签到的过程

打开任意一个签到页面,查看Charles抓包的过程,得到关键js文件
在这里插入图片描述

这个是关键的JS文件
在这里插入图片描述


分析关键性JS文件

这个JS文件很长,虽然内容很多,但是很规范,因此我们很容易分析。
首先直接检索关键字【submit】,说到底这还是个基本表单提交的类型,八九不离十都有submit的关键字
在这里插入图片描述
从JS中,我们得到的表单提交的URL,它有做拼接,从这段function分析来看,这是程序的API库,估计以后APP如果要拓展功能,也是在这里追加内容的。并且,从7529行可以得到,请求的方法是POST。



继续往下检索分析,表单submit的内容,就是方框中的参数:
formWid
address
collectWid
schoolTaskWid
form


后面则是在表单中抓取的内容,也就是对应着我们在APP回答问题时所勾选的选项。
在这里插入图片描述
知道了请求方法是POST,提交的URL以及提交所需要的参数,那么就可以开始写程序主体了。


python脚本的设计

解决登录的问题

登录一定是第一个要解决的问题,如果采用账号密码这种常规登录,会有这样的问题:
1、在某台设备首次登录时,触发短信验证;
2、若在不同的设备重复登录,也会触发短信验证。




因此,不采用账号密码的登录方式,而是采用cookie登录,所以需要抓取用户登录成功后的cookie进行操作,这个也很简单,只需要用户随意访问APP内的任意页面,就拿得到了


图片已做脱敏处理
在这里插入图片描述



解决获取最新签到页面的问题

每天都有新一轮的签到页面来,只有我知道,那没鬼用,要解决的问题是【如何让程序知道新的签到页已经到来】,遗憾的是,我并没有找到,APP是如何向服务器请求当前的签到页状态,但这并不代表我们没办法继续搞下去,因为签到每天都存在,那么表单的id,一定是不一样的,于是我找到了关键参数【collectorWid】,通过这个collectorWid去请求/detailCollector,可以得到formWid等更多的关键数据

图片已做脱敏处理
在这里插入图片描述
参数formWid代表着当前任务的id,collectorWid代表着当前表单的id。
意思是说,我校各个院系,由不同的辅导员,跟踪不同的班级,formWid代表着当天的任务,formWid的数值,每天递增2,有规律可循的变量,就是常量。我们只需要每日递增2即可。而collectorWid则无规律可循,全校这么多个班,系统似乎是随机分配的collectorWid,但是我分析了好几天的签到表单,发现当天和前一天签到的collectorWid,数值相差不会超过100,因此我们可以采用穷举法,逐个逐个排除,判断是否是自己班的表单,则根据另一个参数senderUserName,这个参数很有意思,格式是:系部名称(辅导员姓名),一个辅导员可能负责多个班级,但多个班级却共用一个表单信息,所以,表单可以唯一确定一个wid,最后根据生成的日期,判断是否是当天的签到表,即可完成数据的采集,因此,整个程序的设计可以用如下流程图说明:

在这里插入图片描述

脚本具体代码

dailyCP.py

#!/usr/bin/evn python
#-*- coding:utf-8 -*-

'''
==========================
=====POWER BY python3=====
======Author Task138======
==========================
'''

import requests, json, warnings, time, platform, datetime, threading, random

warnings.filterwarnings('ignore')

def getData(cookie, formWid, collectorWid):

    info = {
    
    }

    info['formWid'] = formWid

    headers = {
    
    
        'Host': '这里填写抓包得到的学校域名',
        'Content-Type': 'application/json',
        'Cpdaily-Extension': '7Q881vmOiX7jaGILUzg4S6KVHTG5EDnVrG5NYAZnpa/uwvii8FC40W4bFMa4 +lHHYuaVTYdvhh+gdoeKP2pml9LDdIzKZZiBi20XZlVIp07XBJcr1r/wUHji GQNYJ+T+w4sSt8ybYOHUw8PYAojN4iTtMN/7NpO+J1Py5NeN9y4gbtfRUuzi 73aLmYJTQhUpcX/f/HC1DZ/gdQA0t/RkWd5g9dQkmiKtqDIqzemjztYCGaYf Om87UgnmqaNshpT6yiHs7Zpxg/NxecW1FJ4Xxdxq+agPWR7/',
        'Cookie': cookie,
        'Accept': '*/*',
        'Accept-Language': 'zh-cn',
        'Accept-Encoding': 'gzip, deflate, br',
        'User-Agent': '%E4%BB%8A%E6%97%A5%E6%A0%A1%E5%9B%AD/4 CFNetwork/1126 Darwin/19.5.0',
        'Connection': 'keep-alive'
    }

    url = 'https://这里填写抓包得到的学校域名/wec-counselor-collector-apps/stu/collector/getFormFields'

    body = {
    
    
        'formWid' : formWid
    }

    data = json.dumps(body)

    req = requests.post(url=url, data=data, verify=False, headers=headers)
    response = json.loads(req.text)

	# 签到表的内容抓取,各个学校内容不同,此处并不通用
    info['title'] = {
    
    
        'title1' : response['datas']['rows'][0]['title'],
        'title2' : response['datas']['rows'][1]['title'],
        'title3' : response['datas']['rows'][2]['title'],
        'title4' : response['datas']['rows'][3]['title'],
        'title5' : response['datas']['rows'][4]['title'],
    }

    wid1 = response['datas']['rows'][0]['wid']
    itemWid1 = response['datas']['rows'][0]['fieldItems'][0]['itemWid']
    itemWid2 = response['datas']['rows'][1]['fieldItems'][0]['itemWid']
    itemWid3 = response['datas']['rows'][2]['fieldItems'][0]['itemWid']
    itemWid4 = response['datas']['rows'][3]['fieldItems'][0]['itemWid']
    itemWid5 = response['datas']['rows'][4]['fieldItems'][0]['itemWid']

    info['wid'] = {
    
    
        'wid1' : wid1,
        'wid2' : str(int(wid1)+1),
        'wid3' : str(int(wid1)+2),
        'wid4' : str(int(wid1)+3),
        'wid5' : str(int(wid1)+4),
    }

    info['itemWid'] = {
    
    
        'itemWid1' : itemWid1,
        'itemWid2' : itemWid2,
        'itemWid3' : itemWid3,
        'itemWid4' : itemWid4,
        'itemWid5' : itemWid5,
    }

    url = 'https://这里填写抓包得到的学校域名/wec-counselor-collector-apps/stu/collector/detailCollector'

    new_collectWid = ''
    schoolTaskWid = ''
    # 撞击阀值
    thread = 100
    for i in range(thread+1):
        body = {
    
    
            'collectorWid': str(int(collectorWid) + i)
        }
        data = json.dumps(body)
        req = requests.post(url=url, data=data, verify=False, headers=headers)
        response = json.loads(req.text)
        # 获取辅导员信息,判断是否为自己的辅导员
        try:
            senderUserName = response['datas']['collector']['senderUserName']
            createTime = response['datas']['collector']['createTime'].split(" ")[0]
            now = datetime.datetime.today()
            date = now.strftime('%Y-%m-%d')

        except:
            print(response)
            continue
        if ('这里填写辅导员姓名' in senderUserName) and (date == createTime):
            schoolTaskWid = response['datas']['collector']['schoolTaskWid']
            new_collectWid = response['datas']['collector']['wid']
            info['schoolTaskWid'] = schoolTaskWid
            info['collectWid'] = new_collectWid

            if new_collectWid != collectorWid:
                with open('Wid.json', 'w') as fp3:
                    new_data = '{"formWid":"%s","collectWid":"%s"}' % (formWid, new_collectWid)
                    fp3.write(new_data)
                    fp3.close()
                    print('更新成功,当前数值:')
                    print('formWid [ %s ]' % formWid)
                    print('collectWid [ %s ]' % new_collectWid)

            break

    return info

def submitForm(cookie, address, data, sleep_time, username):
    now = datetime.datetime.today()
    delta = datetime.timedelta(days=13)

    date = now - delta
    if platform.system() == 'Windows':
        date = date.strftime('%#m月%d日')
    else:
        date = date.strftime('%-m月%d日')

    # print(data)
    headers = {
    
    
        'Host': '这里填写抓包得到的学校域名',
        'Content-Type': 'application/json',
        'Cpdaily-Extension': '7Q881vmOiX7jaGILUzg4S6KVHTG5EDnVrG5NYAZnpa/uwvii8FC40W4bFMa4 +lHHYuaVTYdvhh+gdoeKP2pml9LDdIzKZZiBi20XZlVIp07XBJcr1r/wUHji GQNYJ+T+w4sSt8ybYOHIvtRnqKqx4LxgLuk5oxQ+RfD4W6YbJ21i1zjDNJgN EREKlCSJjrL2C9OeaF5K3YZVLgCv5LSf4xvTfRBsoc9DTSZp33zdV0X99esd xmuTqP+lwcEpMKvrsTWJFwJI5E0/+id7f5PAbj355ZJnrxl+',
        'Cookie': cookie,
        'Accept': '*/*',
        'Accept-Language': 'zh-cn',
        'Accept-Encoding': 'gzip, deflate, br',
        'User-Agent': '%E4%BB%8A%E6%97%A5%E6%A0%A1%E5%9B%AD/1 CFNetwork/1126 Darwin/19.5.0',
        'Connection': 'keep-alive'
    }

    url = 'https://这里填写抓包得到的学校域名/wec-counselor-collector-apps/stu/collector/submitForm'
    
    # 构造提交表单的内容
    body = {
    
    
        "formWid": data['formWid'],
        "address": address,
        "collectWid": data['collectWid'],
        "schoolTaskWid": data['schoolTaskWid'],
        "form": [{
    
    
            "wid": data['wid']['wid1'],
            "formWid": data['formWid'],
            "fieldType": 2,
            "title": data['title']['title1'],
            "description": "",
            "minLength": 0,
            "sort": "1",
            "maxLength": 'null',
            "isRequired": 1,
            "imageCount": 'null',
            "hasOtherItems": 0,
            "colName": "field001",
            "value": "体温正常",
            "minValue": 0,
            "maxValue": 0,
            "isDecimal": 'true',
            "fieldItems": [{
    
    
                "itemWid": data['itemWid']['itemWid1'],
                "content": "体温正常",
                "isOtherItems": 0,
                "contendExtend": "",
                "isSelected": 'null'
            }]
        }, {
    
    
            "wid": data['wid']['wid2'],
            "formWid": data['formWid'],
            "fieldType": 3,
            "title": data['title']['title2'],
            "description": "(可多选)",
            "minLength": 0,
            "sort": "2",
            "maxLength": 'null',
            "isRequired": 1,
            "imageCount": 'null',
            "hasOtherItems": 1,
            "colName": "field002",
            "value": "",
            "minValue": 0,
            "maxValue": 0,
            "isDecimal": 'true',
            "fieldItems": [{
    
    
                "itemWid": data['itemWid']['itemWid2'],
                "content": "未离开居住地",
                "isOtherItems": 0,
                "contendExtend": "",
                "isSelected": 'null'
            }]
        }, {
    
    
            "wid": data['wid']['wid3'],
            "formWid": data['formWid'],
            "fieldType": 3,
            "title": data['title']['title3'],
            "description": "(可多选)",
            "minLength": 0,
            "sort": "3",
            "maxLength": 'null',
            "isRequired": 1,
            "imageCount": 'null',
            "hasOtherItems": 0,
            "colName": "field003",
            "value": "",
            "minValue": 0,
            "maxValue": 0,
            "isDecimal": 'true',
            "fieldItems": [{
    
    
                "itemWid": data['itemWid']['itemWid3'],
                "content": "无相关接触史",
                "isOtherItems": 0,
                "contendExtend": "",
                "isSelected": 'null'
            }]
        }, {
    
    
            "wid": data['wid']['wid4'],
            "formWid": data['formWid'],
            "fieldType": 3,
            "title": data['title']['title4'],
            "description": "(可多选)",
            "minLength": 0,
            "sort": "4",
            "maxLength": 'null',
            "isRequired": 1,
            "imageCount": 'null',
            "hasOtherItems": 1,
            "colName": "field004",
            "value": "",
            "minValue": 0,
            "maxValue": 0,
            "isDecimal": 'true',
            "fieldItems": [{
    
    
                "itemWid": data['itemWid']['itemWid4'],
                "content": " 健康,没有出现相关疾病症状",
                "isOtherItems": 0,
                "contendExtend": "",
                "isSelected": 'null'
            }]
        }, {
    
    
            "wid": data['wid']['wid5'],
            "formWid": data['formWid'],
            "fieldType": 3,
            "title": data['title']['title5'],
            "description": "(可多选)(仅填现在与您共同生活的家人情况)",
            "minLength": 0,
            "sort": "5",
            "maxLength": 'null',
            "isRequired": 1,
            "imageCount": 'null',
            "hasOtherItems": 1,
            "colName": "field005",
            "value": "",
            "minValue": 0,
            "maxValue": 0,
            "isDecimal": 'true',
            "fieldItems": [{
    
    
                "itemWid": data['itemWid']['itemWid5'],
                "content": "所有家人身体均健康,正常",
                "isOtherItems": 0,
                "contendExtend": "",
                "isSelected": 'null'
            }]
        }]
    }

    data = json.dumps(body)
    # time.sleep(sleep_time)

    req = requests.post(url=url, headers=headers, data=data, verify=False)
    response = req.text

    if "SUCCESS" in response:
        print('[ %s ]签到成功' % username)
        return True
    elif "该收集已填写无需再次填写" in response:
        print('[ %s ]签到成功' % username)
        return True
    elif "该收集已结束!" in response:
        print('[ %s ]签到成功' % username)
        return True
    else:
        print('[ %s ]签到失败' % username)
        return False




if __name__ == '__main__':
    success = 0
    failed = 0
    failed_data = []

    with open('test.json', 'r') as fp2:
        accounts = json.load(fp2)
        fp2.close()
    for k, v in accounts.items():
        with open('Wid.json', 'r') as fp:
            data = json.load(fp)
            fp.close()

        formWid = data['formWid']
        address = v['address']
        cookie = v['cookie']
        collectWid = data['collectWid']

        cool_start = random.randint(0, 60)
        cool_end = random.randint(3000, 6000)
        cool = random.randint(cool_start, cool_end)

        # try:
        #     print('[ %s ] 执行签到......' % k)
        #     data = getData(cookie, formWid, collectWid)
        #     t = threading.Thread(target=submitForm, args=(cookie, address, data, cool, k, ))
        #     t.start()
        #     print()
        #     # status = submitForm(cookie, address, data)
        # except:
        #     continue
        print('[ %s ] 正在签到......' % k)
        try:
            formWid = data['formWid']
            address = v['address']
            cookie = v['cookie']
            collectWid = data['collectWid']

            data = getData(cookie, formWid, collectWid)

            print(data)


            status = submitForm(cookie, address, data, cool, k)

            if status:
                success += 1
                print('[ %s ] [ %s ]签到完成' % (k, time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime())))
                print()
            else:
                failed += 1
                failed_data.append(k)
                print('[ %s ] [ %s ]签到失败' % (k, time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime())))
                print()
        except:
            failed += 1
            failed_data.append(k)
            print('[ %s ] 账号失效' % k)
            print()

    print('本次签到共 [ %s ] 人,其中:' % (success + failed))
    print('成功 [ %s ] 人' % success)
    print('失败 [ %s ] 人' % failed)
    if failed_data:
        print('签到失败名单:')
        for i in failed_data:
            print(i)



updateWid.py

#!/usr/bin/evn python
#-*- coding:utf-8 -*-

'''
==========================
=====POWER BY python3=====
======Author Task138======
==========================
'''

import json, requests, warnings, datetime
warnings.filterwarnings('ignore')


with open('Wid.json', 'r') as fp:
    data = json.load(fp)
    fp.close()

formWid = data['formWid']
collectWid = data['collectWid']
new_formWid = str(int(formWid) + 2)
new_collectWid = str(int(collectWid)+1)

with open('Wid.json', 'w') as fp3:
    new_data = '{"formWid":"%s","collectWid":"%s"}' % (new_formWid, new_collectWid)
    fp3.write(new_data)
    fp3.close()
    # print('更新成功,当前数值:')
    # print('formWid [ %s ]' % new_formWid)
    # print('collectWid [ %s ]' % new_collectWid)

def getData(cookie, formWid, collectorWid):
    headers = {
    
    
        'Host': '这里填写抓包得到的学校域名',
        'Content-Type': 'application/json',
        'Cpdaily-Extension': '7Q881vmOiX7jaGILUzg4S6KVHTG5EDnVrG5NYAZnpa/uwvii8FC40W4bFMa4 +lHHYuaVTYdvhh+gdoeKP2pml9LDdIzKZZiBi20XZlVIp07XBJcr1r/wUHji GQNYJ+T+w4sSt8ybYOHUw8PYAojN4iTtMN/7NpO+J1Py5NeN9y4gbtfRUuzi 73aLmYJTQhUpcX/f/HC1DZ/gdQA0t/RkWd5g9dQkmiKtqDIqzemjztYCGaYf Om87UgnmqaNshpT6yiHs7Zpxg/NxecW1FJ4Xxdxq+agPWR7/',
        'Cookie': cookie,
        'Accept': '*/*',
        'Accept-Language': 'zh-cn',
        'Accept-Encoding': 'gzip, deflate, br',
        'User-Agent': '%E4%BB%8A%E6%97%A5%E6%A0%A1%E5%9B%AD/4 CFNetwork/1126 Darwin/19.5.0',
        'Connection': 'keep-alive'
    }


    url = 'https://这里填写抓包得到的学校域名/wec-counselor-collector-apps/stu/collector/detailCollector'

    # 撞击阀值
    thread = 100
    for i in range(thread+1):
        body = {
    
    
            'collectorWid': str(int(collectorWid) + i)
        }
        data = json.dumps(body)
        req = requests.post(url=url, data=data, verify=False, headers=headers)
        response = json.loads(req.text)
        # 获取辅导员信息,判断是否为自己的辅导员
        try:
            senderUserName = response['datas']['collector']['senderUserName']
            createTime = response['datas']['collector']['createTime'].split(" ")[0]
            now = datetime.datetime.today()
            date = now.strftime('%Y-%m-%d')

        except:
            print(response)
            continue
        if ('这里填写辅导员姓名' in senderUserName) and (date == createTime):
            new_collectWid = response['datas']['collector']['wid']

            if new_collectWid != collectorWid:
                with open('Wid.json', 'w') as fp3:
                    new_data = '{"formWid":"%s","collectWid":"%s"}' % (formWid, new_collectWid)
                    fp3.write(new_data)
                    fp3.close()
                    print('更新成功,当前数值:')
                    print('formWid [ %s ]' % formWid)
                    print('collectWid [ %s ]' % new_collectWid)

            break

with open('test.json', 'r') as fp2:
    accounts = json.load(fp2)
    fp2.close()

for k, v in accounts.items():
    with open('Wid.json', 'r') as fp:
        data = json.load(fp)
        fp.close()

    formWid = data['formWid']
    address = v['address']
    cookie = v['cookie']
    collectWid = data['collectWid']
    getData(cookie, formWid, collectWid)

    break



keepAlive.py

#!/usr/bin/env python
#-*- coding:utf-8 -*-

'''

=================================
=================================
=========Author:Task138==========
========Power By Python3=========
=================================
=================================


'''
import json, requests, warnings

warnings.filterwarnings('ignore')


def keepAlive(cookie, formWid):
    headers = {
    
    
        'Host': '这里填写抓包得到的学校域名',
        'Content-Type': 'application/json',
        'Cpdaily-Extension': '7Q881vmOiX7jaGILUzg4S6KVHTG5EDnVrG5NYAZnpa/uwvii8FC40W4bFMa4 +lHHYuaVTYdvhh+gdoeKP2pml9LDdIzKZZiBi20XZlVIp07XBJcr1r/wUHji GQNYJ+T+w4sSt8ybYOHUw8PYAojN4iTtMN/7NpO+J1Py5NeN9y4gbtfRUuzi 73aLmYJTQhUpcX/f/HC1DZ/gdQA0t/RkWd5g9dQkmiKtqDIqzemjztYCGaYf Om87UgnmqaNshpT6yiHs7Zpxg/NxecW1FJ4Xxdxq+agPWR7/',
        'Cookie': cookie,
        'Accept': '*/*',
        'Accept-Language': 'zh-cn',
        'Accept-Encoding': 'gzip, deflate, br',
        'User-Agent': '%E4%BB%8A%E6%97%A5%E6%A0%A1%E5%9B%AD/4 CFNetwork/1126 Darwin/19.5.0',
        'Connection': 'keep-alive'
    }

    url = 'https://这里填写抓包得到的学校域名/wec-counselor-collector-apps/stu/collector/getFormFields'

    body = {
    
    
        'formWid': formWid
    }

    data = json.dumps(body)

    req = requests.post(url=url, data=data, verify=False, headers=headers)
    response = json.loads(req.text)

    status = response['message']
    return status

if __name__ == '__main__':
    with open('test.json', 'r') as fp2:
        accounts = json.load(fp2)
        fp2.close()
    for k, v in accounts.items():
        with open('Wid.json', 'r') as fp:
            data = json.load(fp)
            fp.close()

        formWid = data['formWid']
        address = v['address']
        cookie = v['cookie']
        collectWid = data['collectWid']

        status = keepAlive(cookie, formWid)
        if status == 'SUCCESS':
            print('[ %s ] 保活成功' % k)
        else:
            print('[ %s ] 保活失败' % k)



Wid.json

{
    
    "formWid":"XXX","collectWid":"XXXX"}



account.json

{
    
    
  "用户姓名(必须用Unicode编码)": {
    
    
    "cookie": "抓包抓到的cookie",
    "address": "定位地址(必须用Unicode编码)"
  }
}



Linux云服务器部署脚本

目前已知的是,每天8点整,学校会下发新一轮的签到表单,根据网络延迟的不同,可能有1~2分钟的延迟,那么,我每天8点10分,执行update.py,更新最新的id信息;8点20执行签到主程序。还有一个很拿命的是,cookie会过期,需要定期保活,所以,每隔20分钟,执行一次保活。综上,这就要用到Linux自带的crontab计划任务了。

上传脚本以及配置文件到云服务器

首先把所有文件上传到Linux云服务器上,我上传的目录如下图所示
在这里插入图片描述


编写shell脚本

run.sh

#!/bin/bash
current_date=$(date  "+%Y_%m_%d")
log_name="${current_date}.log"
if [ ! -f "./log/$log_name" ]; then
        touch ./log/$log_name
fi
current_time=$(date  "+%Y_%m_%d_%H_%M_%S")
echo $current_time >> ./log/$log_name
python3 /data/dailyCP/dailyCP.py >> ./log/$log_name
echo -e >> ./log/$log_name
echo "done"



update.sh

#!/bin/bash
current_date=$(date  "+%Y_%m_%d")
log_name="${current_date}.log"
if [ ! -f "./update_log/$log_name" ]; then
        touch ./update_log/$log_name
fi
current_time=$(date  "+%Y_%m_%d_%H_%M_%S")
echo $current_time >> ./update_log/$log_name
python3 /data/dailyCP/updateWid.py >> ./update_log/$log_name
echo -e >> ./update_log/$log_name
echo "done"



keepAlive.sh

python3 /data/dailyCP/keepAlive.py



编写crontab计划任务

10 8 * * * cd /data/dailyCP && sh update.sh
20 8 * * * cd /data/dailyCP && sh run.sh
*/20 * * * * cd /data/dailyCP && sh keepAlive.sh



缺陷与后期提升

目前脚本已经正常运行了一个多星期,暂时没有发现什么大问题,但依旧是有顾虑的:
1、签到时间绝对固定,固定的可怕,每天都是8点20签到,不早一分,不晚一秒,如果遇到人工审计后台数据,肯定有问题。后期可以追加一个随机时段签到的功能,从而让签到更具隐秘性;
2、如果某一天突然更换了签到表的内容,程序可能会崩溃,从而导致签到的失败,如果真的是这样,就需要重新构造新的表单提交数据,这个暂时没办法做到自适应,能力有限;
3、如果签到失败,没办法及时获取到信息,只能等班委催签。后期可以追加个“签到失败,自动发送邮件提醒”的功能,目前暂时不需要。



参考文献

[1] Python实现今日校园自动签到

猜你喜欢

转载自blog.csdn.net/cbcrzcbc/article/details/107948416