學習通自動簽到源碼

下載鏈接在文末

首先說,實現學習通的簽到功能並不難(包括手勢簽到掃碼簽到什麼什麼的),自己可以抓包找找接口,實在找不到或者嫌麻煩,也可以用我項目裏的這幾個接口也可以。這裏要說的是,其實讓我印象最深刻的是第一次做驗證系統(就是。。。。軟件使用權限口令的生成,怎麼防止第三方解密,以及如何防止用戶二次利用Token,以及怎麼防止用戶修改本地時間達到延長軟件使用期限,還有防止在軟件和服務器通信過程中第三方劫持,限制同一臺機器使用一個Token,並且還要考慮用戶如果在Token沒有失效的情況下再次購買Token,服務器不能因爲MAC和Token不一樣就限制人家吧,還有得防止惡意請求DDOS你的服務器8。。。。。。反正就是巴拉巴拉一大堆需要考慮的問題,不過還好都解決了,完成的不是很困難)
0
下面就寫一下解決這些問題的大體思路8: 首先是從防止第三方惡意請求你的服務器,這個其實考慮過用redis來做,不過。。。。原諒我,沒有用redis擋在前面,我緩解數據庫壓力的方法,採用的是邏輯判斷的方法。就是限定發送的POST請求傳遞過來的數據是我指定的口令加密的數據,並且爲了保證對方使用相同的傳遞的數據發起惡意攻擊,還需要每一個傳遞過來的數據都是唯一的,並且都是某一時刻以後不能重複或者失效的,這裏我是用的就是,把數據和時間戳綁定,解密數據後,只需要客戶端的時間戳和當前服務器的時間戳的差值即可,這裏涉及到傳輸延遲,所以,判斷差值的時候我故意讓他最大傳輸時延爲3秒,然後如果滿足條件,就基本可以斷定是客戶端發來的數據。在這之後,就是要判斷客戶端的Token是否綁定的是他綁定的MAC,其次還要判斷用戶密碼是否已修改以及用戶是否購買的新的口令來更新原來的信息。如下所示,是加密和解密以及進行用戶身份判定的過程,加密沒想到更好的,就直接用的itsdangerous

‘’‘數據加密與綁定’‘’
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
import re
def xxx():
	key = "xxxxxxxxxxxxx"
	s = Serializer(key)
	stp = {'timestp': int(time.time()), 'phone': phone, 'pwd': pwd, 'mac': mac,
	       'token': token}
	m = s.dumps(stp)
	ms = re.findall(r"b'(.*)'", str(m))[0]
	msg = {'data': ms}
	res = requests.post("http://xxxxxxxxxxx/conn_check", data=msg)
	return res

‘’‘服務器端數據的解密以及用戶身份的判定’‘’
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
key = "xxxxxxxxxxxxxx"
s = Serializer(key)
def post(self,response)
	try:
	   timestp_server = int(time())
	   res = s.loads(response.POST.get('data'))
	   # 確保3秒之內傳到服務器
	   if (timestp_server - res['timestp']) < 3:
	       print("server: {}".format(timestp_server))
	       print("user: {}".format(res['timestp']))
	       print("cha: {}".format(timestp_server - res['timestp']))
	       token = res['token']
	       # 判斷token是否存在數據庫(是否被使用過)
	       try:
	           UM = UserMac.objects.get(token=token)
	           # 如果被使用過,就判斷是否是同一個人(mac地址判斷)
	           if UM.mac == res['mac']:
	               # 如果密碼不同,說明人家改密碼了,數據庫也需要修改
	               if UM.password != res['pwd']:
	                   UM.password = res['pwd']
	                   UM.save()
	                   return JsonResponse({'status': 'True'})
	               else:
	                   return JsonResponse({'status': 'True'})
	           else:
	               return JsonResponse({'status': 'Bound MAC address is not local Mac, error'})
	
	       # 如果Token沒被用過,判斷手機號是否存在數據庫
	       except Exception as e:
	           try:
	               UM2 = UserMac.objects.get(phone=res['phone'])
	               # 用戶是來更新數據的
	               UM2.password = res['pwd']
	               UM2.mac = res['mac']
	               UM2.token = token
	               UM2.save()
	               return JsonResponse({'status': 'True'})
	
	           except:
	               # 如果手機號不存在數據庫中,說明用戶第一次註冊,直接向數據庫寫數據
	               usermac = UserMac()
	               usermac.token = token
	               usermac.phone = res['phone']
	               usermac.password = res['pwd']
	               usermac.mac = res['mac']
	               usermac.photo = False
	               usermac.save()
	               return JsonResponse({'status': 'True'})
	   else:
	       return JsonResponse({'status': 'Network reason request timeout, error'})
	except Exception as e:
	   print(e)
	   return JsonResponse({'status': 'Request unofficial, error'})

當然,這裏服務器返回的數據沒有加密,不過不得不考慮到中間被挾持,然後發送假請求給客戶端的情況,加密這裏,我是在用戶獲取7天免費試用期限獲取Token的時候加密的。

然後,再來說一說,獲取7天使用權限生成的Token的時候,我考慮了什麼
其實過程和上面差不多,只不過,這裏需要限制的是用戶的MAC地址。所以,比較容易想到的是,如果用戶之前登陸過,數據庫裏肯定由用戶的MAC信息,所以,就不難想到,當用戶想要獲取對軟件的7天使用權限的時候,只需要判斷用戶的MAC是否已經存在數據庫即可。可是,這裏就要考慮到,如果服務器返回的數據過於簡單,會被第三方劫持利用,所以,必須對服務器返回的數據進行加密,客戶端的判斷方法和上面說的服務器的判斷方法差不多,進行時間戳和消息綁定,這樣就保證了客戶端接收到的數據唯一性,客戶端可以對時間戳判斷,如果是3秒之內發送過來的數據,就接收,如果不是,就直接拋異常,下面就是新用戶免費領取7天軟件使用權限的客戶端以及服務器的代碼:

‘’‘服務器端’‘’
class CM(View):
    def get(self, response):
        return JsonResponse({'status': "Nima blew up. Request P. request. Request way. NIMA's wrong. Fuck"})

    def post(self, response):
        try:
            data = response.POST.get('data')
            res = s.loads(data)
            timstp = res['timstp']
            if (time() - timstp) < 3:
                mac = res['mac']
                try:
                    UserMac.objects.get(mac=mac)
                    data = {'status': 'Request unofficial, error', 'timstp': int(time())}
                    resp = re.findall(r"b'(.*)'", str(s.dumps(data)))[0]
                    return JsonResponse({'data': resp})
                except:
                    date = 7 * 3600 * 24
                    sm = Serializer(key, date)
                    stp = {"Expiration_date": date, "timestp": int(time())}
                    m = sm.dumps(stp)
                    ms = re.findall(r"b'(.*)'", str(m))[0]
                    data = {'status': True, 'timstp': int(time()), 'token': ms}

                    resp = re.findall(r"b'(.*)'", str(sm.dumps(data)))[0]
                    return JsonResponse({"data": resp})
            else:
                return JsonResponse({'status': 'Network reason request timeout, error'})
        except Exception as e:
            print(e)
            return JsonResponse({'status': 'Request unofficial, error'})

---------------------------------------------------------------------------------------------------


‘’‘客戶端’‘’
import json
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
import requests
import uuid
import re
import time

key = "..................."
s = Serializer(key)
node = uuid.getnode()
mac = uuid.UUID(int=node).hex[-12:]
stp = {"mac": mac, "timstp": int(time.time())}
m = s.dumps(stp)
ms = re.findall(r"b'(.*)'", str(m))[0]

res = json.loads(requests.post("http://.............../CM", data={"data": ms}).content.decode())
try:
    datap = s.loads(res['data'])
    if int(time.time()) - datap['timstp'] < 3:
        if datap['status'] == True:
            ms = datap['token']
            print('''
=======================================================================================

        免費Token申請成功,【 注意:】在 config.ini中填寫的時候,請保證口令爲一行
        
        下面便是已申請的 Token

========================================================================================
            ''')
            print(ms)
            time.sleep(600)
        else:
            print('''
=======================================================================================

            向服務器所求 Token 口令失敗,因:用戶已經領取過一次免費的Token了

========================================================================================
            ''')
            time.sleep(600)
except Exception as e:
    print('''
=======================================================================================

                            非法回覆,不是服務器發來的消息

========================================================================================
    ''')
    time.sleep(600)

下面,是大體簽到代碼的實現,不難實現,就不多說了,其中去除了一些敏感信息。

import multiprocessing
import requests
import json
import smtplib
from email.mime.text import MIMEText
import time
import re
import base64
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
import uuid
from multiprocessing import Process


class Baopo:
    def __init__(self):
        self.task_list = []
        self.alog_list = []
        '''讀取配置文件中的配置信息'''
        with open('config.ini', 'rb') as f:
            self.config = json.loads((f.read()).decode())
        '''郵件信息初始化'''
        self.sender = '........@...........'
        self.password = '...............'
        self.sendTo = self.config['sendTo']
        self.mail_host = "smtp.163.com"
        try:
            # 獲取時間戳以及約定的時間
            self.Time = self.config['Token']
            s = Serializer("......................")
            self.epc = s.loads(self.Time)['Expiration_date']
            self.startime = int(s.loads(self.Time)['timestp'])
        except:
            print('''
    程序無法正常運行,因爲您的使用期限已到,請向開發者購買Token後繼續使用。
            ''')
            time.sleep(600)
            return

        # 請求標準時間
        standerd_url = "http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json"
        self.timep = int(json.loads(requests.get(standerd_url).content.decode())['result']['timestamp'])
        # 獲取網卡的MAC地址
        node = uuid.getnode()
        self.mac = uuid.UUID(int=node).hex[-12:]

        '''學習通接口相關信息初始化'''
        self.Signin_url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax?activeId={}&uid={}&clientip=&appType=15&fid={}&address={}&latitude={}&longitude={}"
        self.actived_url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist?courseId="
        self.getclass_url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata?view=json&rss=1"
        self.index_url = "http://i.mooc.chaoxing.com/space/index?"
        self.login_url = "https://passport2.chaoxing.com/fanyalogin"
        self.login_data = {
            "fid": "-1",
            "uname": self.config['username'],
            'refer': 'http://fxlogin.chaoxing.com/findlogin.jsp?backurl=http://www.chaoxing.com/channelcookie',
            "password": re.findall(r"b'(.*)'", str(base64.b64encode(self.config['password'].encode())))[0],
            "t": "true"
        }

        # 僞造請求頭
        self.headers = {
            "Referer": "https://passport2.chaoxing.com/login?fid=&newversion=true&refer=http://fxlogin.chaoxing.com/findlogin.jsp?backurl=http://www.chaoxing.com/channelcookie",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
        }

    def Sign_Kind_test(self, s, activeId, classId, fid, courseId):
        args = "/widget/sign/pcStuSignController/preSign?" + "activeId={}".format(activeId) + "&classId={}".format(
            classId) + "&fid={}".format(fid) + "&courseId={}".format(courseId)
        response = s.get(url="https://mobilelearn.chaoxing.com" + args, headers=self.headers)
        # print("檢測鏈接:https://mobilelearn.chaoxing.com{}".format(args))
        return response

    def upload_img(self, s):
        url = 'https://pan-yz.chaoxing.com/upload?_token=5d2e8d0aaa92e3701398035f530c4155'
        mobile_header = {
            'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 10; MI 8 MIUI/20.2.27)'
                          ' com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)'
                          '_994222229cb94d688c462b7257600006',
            'Host': 'pan-yz.chaoxing.com'
        }
        img = {}
        try:
            img = {"file": ("Sign.jpg", open("./IMG/M.jpg", "rb"))}
        except:
            print("圖片未找到,如果出現了此提示,則說明您未設置拍照簽到的圖片,已爲您發送系統默認的圖片,若想自定義照片,請把照片命名爲 'M.jpg' 後放在 'IMG' 文件夾中")
            if self.config["gender"] == "男":
                return "9cb266884f96bb598a2ee197268a8baf"
            else:
                return "30f6e2f3c1259aefa7c174f3f379e9cd"
        i_data = {'puid': "80421235"}
        response = s.post(url=url, headers=mobile_header, data=i_data, files=img)
        return response.json().get('objectId')

    def photoSign(self, s, objectId, activeId, courseId, fid):
        """拍照簽到"""
        url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax?activeId={}&classId=&fid={}&courseId={}&objectId={}".format(
            activeId, fid, courseId, objectId)
        response = s.get(url=url, headers=self.headers)
        return response.text

    # 傳入 課程名 / 教師姓名 / 簽到時間 / 學生人數 / 簽到形式 / 剩餘簽到時間
    def send_email(self, className, teacherName, localTime, stuSum, signKind, Remaining_time, img):
        receiver = []
        if img == "":
            content = '''
<div style="width: 360px;margin: auto;overflow: hidden"><div style="width: 360px;text-align: center"><h1 style="color: mediumseagreen;font-family: 楷體">秒懂簽到任務提醒</h1></div><div style="font-family: '楷體';width: 360px;text-align: center;color: red;font-size: 12px;font-weight: bolder">        以免老師察覺到您的不在場,請儘快登錄學習通完成本次課堂任務</div><br><div style="font-family: 楷體;"><div style="width: 358px;border: double 1px green;text-align: center"><div style="text-align: center;padding: 5px"><div style="width: 358px;"><table style="height: 180px"><p></p><tr><div style="font-size: 16px;text-align: center;width: 358px;color: mediumseagreen;font-weight: bolder">                                老師剛剛發起了課堂{}</div></tr><tr><td style="width: 60px;font-weight: bolder;font-size: 12px;color: mediumseagreen">√</td><td style="width: 10px">&nbsp;</td><td style="width: 50px;font-size: 12px;color: red;font-weight: bolder;text-align: right">                                課程定位</td><td style=" width: 200px;text-align: left;font-size: 10px;font-weight: bolder"><span                                    style="font-weight: bolder;color: red;text-align: left">:{}</span></td></tr><tr><td style="font-weight: bolder;font-size: 12px;color: mediumseagreen">√</td><td>&nbsp;</td><td style="font-size: 12px;color: red;font-weight: bolder;text-align: right">任務類型</td><td style="text-align: left;font-size: 12px;font-weight: bolder"><span                                    style="font-weight: bolder;color: red;text-align: left">:{}</span></td></tr><tr><td style="font-weight: bolder;font-size: 12px;color: mediumseagreen">√</td><td>&nbsp;</td><td style="font-size: 12px;color: red;font-weight: bolder;text-align: right">教師姓名</td><td style="text-align: left;font-size: 12px;font-weight: bolder"><span                                    style="font-weight: bolder;color: red;text-align: left">:{}</span></td></tr><tr><td style="font-weight: bolder;font-size: 12px;color: mediumseagreen">√</td><td>&nbsp;</td><td style="font-size: 12px;color: red;font-weight: bolder;text-align: right">課堂人數</td><td style="text-align: left;font-size: 12px;font-weight: bolder"><span                                    style="font-weight: bolder;color: red;text-align: left">:{}</span></td></tr><tr><td style="font-weight: bolder;font-size: 12px;color: mediumseagreen">√</td><td>&nbsp;</td><td style="font-size: 12px;color: red;font-weight: bolder;text-align: right">剩餘時間</td><td style="text-align: left;font-size: 12px;font-weight: bolder"><span                                    style="font-weight: bolder;color: red;text-align: left">:{}</span></td></tr></table></div></div><br></div><p></p><a style="font-weight: bolder;font-family: '宋體';color: crimson;text-decoration: none" target="_blank"           href="https://blog.csdn.net/weixin_44449518"><div style="background-color: lightgreen;border: 1px solid red;width: 358px;height: 50px;text-align: center;line-height: 50px">                點擊鏈接 秒懂 開發者</div></a></div></div>
                '''.format(signKind, className, signKind, teacherName, stuSum, Remaining_time)
            title = "老師發起新的課堂任務了!!!"
        else:
            content = '''
    <div style="width: 302px;margin: auto;overflow: hidden"><h1 style="color: mediumseagreen;font-family: 楷體">秒懂簽到 世界如此簡單</h1><div style="font-family: 楷體;"><div style="font-size: 10px">            尊敬的用戶您好:<br>            &nbsp;&nbsp;&nbsp;&nbsp;剛剛由<span style="color: red">{}</span> 老師發起的簽到任務已幫您簽到成功,簽到系統仍然繼續爲您監測簽到任務.            '秒懂簽到',用技術改變時代生活節奏<br><br></div><div style="width: 300px;border: double 1px green"><div style="text-align: center;padding: 5px"><div style="width: 270px;"><table style="text-align: right"><tr><span style="color: mediumseagreen;font-weight: bolder">簽到成功</span></tr><tr><td>√</td><td>&nbsp;</td><td style="font-size: 10px">課程名稱</td><td style="text-align: left;font-size: 9px;font-weight: bolder">:{}</td></tr><tr><td>√</td><td>&nbsp;</td><td style="font-size: 10px">完成時間</td><td style="text-align: left;font-size: 9px;font-weight: bolder">:{}</td></tr><tr><td>√</td><td>&nbsp;</td><td style="font-size: 10px">簽到類型</td><td style="text-align: left;font-size: 9px;font-weight: bolder">:{}</td></tr><tr><td>√</td><td>&nbsp;</td><td style="font-size: 10px">教師姓名</td><td style="text-align: left;font-size: 9px;font-weight: bolder">:{}</td></tr><tr><td>√</td><td>&nbsp;</td><td style="font-size: 10px">課堂人數</td><td style="text-align: left;font-size: 9px;font-weight: bolder">:{}</td></tr><tr><td>√</td><td>&nbsp;</td><td style="font-size: 10px">剩餘時間</td><td style="text-align: left;font-size: 9px;font-weight: bolder">:{}</td></tr></table></div></div><br></div><p></p><a style="font-weight: bolder;font-family: '宋體';color: crimson;text-decoration: none" target="_blank"           href="https://blog.csdn.net/weixin_44449518"><div style="background-color: lightgreen;border: 1px solid red;width: 300px;height: 50px;text-align: center;line-height: 50px">                點擊鏈接 秒懂 開發者</div></a><p></p><a target="_blank" style="text-decoration: none" href="{}"><div style="border: 1px solid red;background-color: lightgreen;line-height: 30px;width: 300px;height:30px;text-align: center;font-weight: bolder;font-family: '宋體';color: crimson">                拍照簽到照片預覽</div></a><p></p><a target="_blank" href="{}"><img src="{}"></a></div></div>
            '''.format(teacherName, className, localTime, signKind, teacherName, stuSum, Remaining_time, img, img, img)
            title = '老師發起的簽到任務已自動簽到成功'
        message = MIMEText(content, 'html', 'utf-8')
        receiver.append(self.sendTo)
        message['From'] = "秒懂簽到系統 <{}>".format(self.sender)
        message['To'] = ",".join(receiver)
        # print(message['To'])
        message['Subject'] = title

        try:
            smt = smtplib.SMTP_SSL(self.mail_host, 465)
            smt.login(self.sender, self.password)
            smt.sendmail(self.sender, receiver, message.as_string(), )
            print('''
=====================================
||                                 ||
            郵件發送成功
        {} 
||                                 ||
=====================================
            '''.format(localTime))
        except smtplib.SMTPException as e:
            print(e)
            print("郵件發送失敗!!!")

    def todo(self):
        '''獲取cookies'''
        s = requests.Session()
        try:
            s.post(url=self.login_url, headers=self.headers, data=self.login_data)
            class_list_html = s.get(self.getclass_url, headers=self.headers).content.decode()
            class_list_dict = json.loads(class_list_html)['channelList']
            from tts import Test_check
            check = Test_check()
            res = json.loads(check.run(token=self.Time, phone=self.config['username'], pwd=self.config['password'],
                                       mac=self.mac).content.decode())
            if res['status'] != 'True':
                print('''
====================================================

    {}

====================================================
                '''.format(res['status']))
                time.sleep(600)
                return

        except Exception as e:
            print(e)
            print('''
=====================================

    用戶名或密碼錯誤,登錄失敗
    
=====================================
            ''')
            time.sleep(600)
            return

        courseId = []
        classId = []
        className = []
        teacherName = []
        stuSum = []
        uid = s.cookies['UID']
        fid = s.cookies['fid']

        '''對 uid classId courseId 進行初始化'''
        for temp in class_list_dict:
            try:
                courseId.append(temp['content']['course']['data'][0]['id'])
            except Exception as e:
                continue
            classId.append(temp['key'])
            className.append(temp['content']['course']['data'][0]['name'])
            teacherName.append(temp['content']['course']['data'][0]['teacherfactor'])
            stuSum.append(temp['content']['studentcount'])

        if len(self.task_list) == 0:
            '''進行課程列表的獲取'''
            count = 0
            print("=" * 150 + "\n")
            for name in className:
                if ((count + 1) % 3 == 0):
                    if count == len(className) - 1:
                        print("【{}】".format(count) + name, end="")
                    else:
                        print("【{}】".format(count) + name, end="\n")
                else:
                    if count == len(className) - 1:
                        print("【{}】".format(count) + name, end="")
                    else:
                        print("【{}】".format(count) + "%-30s" % name, end="\t\t\t")
                count = count + 1
            print("\n" + "=" * 150)
            task_list_str = input("請輸入要檢測的課程前面'【】'中的序號,多個課程之間用【空格】隔開:(例如:4 5 10)\n")
            self.task_list = task_list_str.split(" ")

        '''內置程序啓動'''
        from luping import Run
        r = Run()
        p1 = Process(target=r.todo, kwargs={"phone": self.config['username']})
        p1.start()

        while True:
            '''進行課程任務列表的獲取,判斷是否有簽到任務,如果有就完成簽到'''
            for i in range(len(classId)):
                if str(i) in self.task_list:
                    json_active = s.get(
                        self.actived_url + str(courseId[i]) + "&classId=" + str(classId[i]) + "&uid=" + uid,
                        headers=self.headers).content.decode()
                    # print(self.actived_url + str(courseId[i]) + "&classId=" + str(classId[i]) + "&uid=" + uid)
                    mmm = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist?courseId=210811209&classId=22346919&uid=79654370"

                    try:
                        res = json.loads(json_active)
                    except:
                        continue
                    activeList = res['activeList']
                    if self.config["gender"] == "男":
                        argsp = "9cb266884f96bb598a2ee197268a8baf"
                    else:
                        argsp = "30f6e2f3c1259aefa7c174f3f379e9cd"

                    for j in range(len(activeList)):
                        activeType = activeList[j]['activeType']
                        if activeType == 2 and activeList[j]['status'] == 1:
                            # 判斷是否爲拍照簽到?
                            activeId = activeList[j]['id']
                            response = self.Sign_Kind_test(s, activeId, classId[j], fid, courseId[j])
                            signKind = activeList[j]['nameOne']
                            Remaining_time = activeList[j]['nameFour']

                            if re.findall(r'手機拍照', response.text):
                                # 上傳拍照照片
                                objectid = self.upload_img(s)
                                # 進行拍照簽到
                                msg = self.photoSign(s, objectid, activeId, courseId[j], fid)
                                argsp = objectid
                            else:
                                msg = s.get(
                                    self.Signin_url.format(activeId, uid, fid, self.config["address"],
                                                           self.config["latitude"],
                                                           self.config["longitude"],
                                                           ),
                                    headers=self.headers).content.decode()
                            if msg == "您已簽到過了":
                                continue
                            else:
                                localTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                                print('''
=====================================
||                                 ||
               簽到成功 
         {}
||                                 ||
=====================================
                                    '''.format(localTime))
                                img_url = "http://pks3.ananas.chaoxing.com/star3/312_412c/{}.jpg".format(argsp)
                                goto = ""
                                # send_email(self, className, teacherName, localTime, stuSum, signKind)
                                self.send_email(className[i], teacherName[i], localTime, stuSum[i], signKind,
                                                Remaining_time, img_url)

                        if activeList[j]['id'] not in self.alog_list:
                            if activeType in [14, 43, 11, 42, 23, 35, 17, 45] and activeList[j]['status'] == 1:
                                localTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                                typeACT = ""
                                if activeType == 14:
                                    typeACT = "問卷"
                                if activeType == 43:
                                    typeACT = "投票"
                                if activeType == 11:
                                    typeACT = "選人"
                                if activeType == 42:
                                    typeACT = "測驗"
                                if activeType == 23:
                                    typeACT = "評分"
                                if activeType == 35:
                                    typeACT = "分組任務"
                                if activeType == 17:
                                    typeACT = "直播"
                                if activeType == 45:
                                    typeACT = "通知"
                                self.alog_list.append(activeList[j]['id'])
                                print('''
+++++++++++++++++++++++++++++++++++++
++                                 ++
            老師發起{} 
         {}
++                                 ++
+++++++++++++++++++++++++++++++++++++
                                    '''.format(typeACT, localTime))
                                img_url = ""
                                signKind = typeACT
                                Remaining_time = activeList[j]['nameFour']
                                self.send_email(className[i], teacherName[i], localTime, stuSum[i], signKind,
                                                Remaining_time, img_url)

            print("本次檢測結束,1分鐘後任務重新啓動")
            time.sleep(60)

    def run(self):
        end = self.startime + self.epc
        if end >= self.timep:
            print('''
        您的使用時間還剩 {} 小時 {} 分鐘 {} 秒,以免影響您的正常使用
        請聯繫開發者購買更多使用時間
            '''.format(int((end - self.timep) / 3600), int(((end - self.timep) % 3600) / 60),
                       int(((end - self.timep) % 3600) % 60)))
            while True:
                try:
                    self.todo()
                except Exception as e:
                    print(e)
                    print("‘Remote end closed connection without response’如果看到這一句話,八成是被反爬了,不過不用擔心,程序會自動重啓")
        else:
            print('''
    程序無法正常運行,因爲您的使用期限已到,請向開發者購買Token後繼續使用。
            ''')
            time.sleep(600)


if __name__ == '__main__':
    multiprocessing.freeze_support()
    print('''
==================================================================================
||
||	 【1】 Name of the project: 秒懂簽到系統
||
||	 【2】              author: Caiden_Micheal
||
||	 【3】      GitHub address: https://github.com/Meterprete?tab=repositories
||
||	 【4】    Personal mailbox: [email protected]
||
||	           			  time: 2020.3.17
||
==================================================================================
            ''')
    print('''
=====================================

        請稍等,系統正在初始化中

=====================================
            ''')
    bopo = Baopo()
    try:
        bopo.run()
    except Exception as e:
        print(e)
        print('''
=====================================

            程序異常終止

=====================================
        ''')
        time.sleep(600)

當然,上面說的只不過是整個項目中的冰山一角,整個項目的實現難度爲 中,除了可以說出來的這些,還有一些不爲人知代碼藏在項目裏,可以自取慢慢研究8,就說到這裏了。說多了浪費時間,不如自己拿去研究研究。

新用戶成功申請獲得免費Token截圖:在這裏插入圖片描述

2020.3.26更新後

(免去認證與授權的繁瑣,可脫離服務器運行)

正常運行截圖:在這裏插入圖片描述

簽到成功後郵件提醒截圖:在這裏插入圖片描述

其他的還有很多東西,就不一個一個拿出來展示了,文檔鏈接:https://doc.weiyun.com/4ae7ebaeda174e5c235bfb86feee4311

下載的方式:


【2020.3.23更新】**新增加了**自定義拍照簽到時的照片,以及位置簽到的地點自定義,外加投票 / 選人 / 測驗 / 問卷 / 評分 / 分組任務 / 直播 / 通知 秒發郵件提醒,等有時間了再用QTi寫個界面。【已廢棄】


【2020.3.26更新】**新增加了**在保留了3.23日更新功能的前提下,廢除與服務器連接限制,此次與服務器脫離,免認證,完全免費無限制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章