专属我的味道

云课堂-智慧职教(职教云)自动签到云函数代码

代码仅供逆向学习参考
2020.07.25 更新修复缺少的时间戳和加密信息
2020.07.05 更新修复缺少机型导致的信息错误
2020.05.31 更新修复使用特殊符号密码的报错
2020.05.25 更新修复新增newToken验证的报错

云函数自动签到视频教程bilibili在线播放
使用腾讯云函数,设置语言python3.6,模板空白函数
将index.py改成zjy.py,执行方法改成zjy.auto_signin
将下面代码的内容复制到云函数的zjy.py,修改网页中zjy.py的用户名密码
设置内存64MB,超时4s
设置环境变量TZ=Asia/Shanghai即可
添加触发方式,使用自定义触发

注意: 运行次数过多将产生费用参考云函数定价
免费额度:资源使用量40万GBs 调用次数100 万次
计费定价(超出免费额度部分):资源使用量0.00011108元/GBs 调用次数0.0133元/万次 外网出流量0.8元/GB
资源使用量 = (内存/1024) × (运行时间(毫秒)/1000)
因账单明细费用(计费)最多支持8位小数,而账户支付金额(扣费)最多支持2位小数,故在高精度计费和低精度扣费之间存在精度差异,系统会按高精度计费与按低精度扣费之间的差额进行自动精度差异调整。
以下面的实时签到为例
资源使用量 = (64/1024) × (700/1000) = 0.04375 GBs
调用次数= 20 × (19-7+1) x 60 x (5/60) = 18720次
资源使用量和调用次数都没有超出免费额度,所以只需要支付外网流量
每次调用的外网流量平均应该5K不到,实测定时签到在月度计费精度差异下可以免去费用(单个实时签到应该也行)

以下是触发参考,更多自定义触发参考cron文档
定时签到参考
9点50左右有一次签到(星期二到星期五的上午9点45-54的每五秒钟执行一次

*/5 45-54 9 * * TUE-FRI * 

13点40左右有一次签到(星期一和星期三的下午1点35-44的每五秒钟执行一次)

*/5 35-44 13 * * MON,WED * 

实时签到参考(频率高时,返回值是Unicode编码,Unicode转中文)
上午7点到19点不定时会有签到(星期一到星期五的上午7点到19点的每五秒执行一次)

*/5 * 7-19 * * MON-FRI * 

QQ截图20200324154657.png
支持常规、手势、二维码签到
代码如下,开启邮箱通知,修改mailConfig中Eanbled的值False为True,按照提示配置SMTP,开启邮箱记得调整超时。开启server酱,修改serverChan中Eanbled的值False为True,并配置SCKEY。

# -*- coding: utf8 -*-
import requests,json,time,smtplib,hashlib
from email.mime.text import MIMEText
from email.header import Header
def auto_signin(event, context):
    userName,userPwd="账号","密码"
    mailConfig={
            "enabled": False,"smtp_server": "SMTP地址","smtp_port": "SMTP端口","from_addr": "发件人邮箱","from_pwd": "发件人密码","to_addr": "收件人邮箱"
            #示例#"enabled": True,"smtp_server": "smtp.domain.com","smtp_port": "25","from_addr": "from@domain.com","from_pwd": "password","to_addr": "to@domain.com"
        }
    serverChan={
            "enabled": False,"SCKEY": "在这填写server酱的SCKEY"
            #示例#"enabled": True,"SCKEY": "SCU9086fd99b24f4d1665e79f4601b6b518T7e719eca372192c4ca"
        }
    url_api="https://zjyapp.icve.com.cn/newMobileAPI/"
    equipmentModel="Xiaomi Redmi K20 Pro"
    equipmentApiVersion=10
    equipmentAppVersion="2.8.29"
    emit = str(int(time.time())) + "000"
    basicData={"equipmentAppVersion": equipmentAppVersion,"equipmentApiVersion":equipmentApiVersion,"equipmentModel":equipmentModel}
    headers = {
            "Content-Type": "application/x-www-form-urlencoded","Host": "zjyapp.icve.com.cn","Connection": "Keep-Alive","Accept-Encoding": "gzip","User-Agent": "okhttp/4.5.0","emit":emit,"device":getDevice(equipmentModel,str(equipmentApiVersion),equipmentAppVersion,emit)
        }
    userData = {"clientId": "f47d9901259e48a982eb9af711410aba", "sourceType": "2", "userPwd": userPwd, "userName": userName,
                 "appVersion": equipmentAppVersion}
    userData.update(basicData)
    session = requests.Session()
    login=session.post(url_api + "MobileLogin/newSignIn", data=userData,headers=headers)
    loginInfo=json.loads(login.text)
    if loginInfo["code"]!=1:
        return (loginInfo["msg"])
    stuId = loginInfo["userId"]
    faceDate = (time.strftime("%Y-%m-%d", time.localtime()))
    newToken=loginInfo["newToken"]
    todayClassData = {"stuId": stuId, "faceDate": faceDate,"newToken": newToken}
    todayClassData.update(basicData)
    todayClass=session.post(url_api + "faceteach/getStuFaceTeachList", data=todayClassData, headers=headers)
    todayClassInfo=json.loads(todayClass.text)["dataList"]
    result=""
    for i in range(len(todayClassInfo)):
        inClassData = {
            "activityId": todayClassInfo[i]["Id"], "stuId": stuId, "classState": todayClassInfo[i]["state"], "openClassId": todayClassInfo[i]["openClassId"],
            "newToken": newToken
        }
        inClassData.update(basicData)
        inClass=session.post(url_api + "faceteach/newGetStuFaceActivityList", data=inClassData, headers=headers)
        inClassInfo=json.loads(inClass.text)["dataList"]
        for n in range(len(inClassInfo)):
            if inClassInfo[n]["DataType"] == "签到" and inClassInfo[n]["State"] != 3:
                attendData = {
                    "activityId": todayClassInfo[i]["Id"], "openClassId": todayClassInfo[i]["openClassId"], "stuId": stuId, "typeId": inClassInfo[n]["Id"], "type": "1",
                    "newToken": newToken
                }
                attendData.update(basicData)
                attend=session.post(url_api + "faceteach/isJoinActivities", data=attendData,headers=headers)
                attendInfo=json.loads(attend.text)
                if attendInfo["isAttend"] != 1:
                    signInData = {
                    "signId": inClassInfo[n]["Id"], "stuId": stuId, "openClassId": todayClassInfo[i]["openClassId"],"sourceType": "2", "checkInCode": inClassInfo[n]["Gesture"],"activityId": todayClassInfo[i]["Id"],
                    "newToken": newToken
                    }
                    signInData.update(basicData)
                    signIn=session.post(url_api + "faceteach/saveStuSign", data=signInData,headers=headers)
                    signInInfo=json.loads(signIn.text)
                    signInTime=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                    result=result+(todayClassInfo[i]["courseName"] + " " + signInTime + " " + signInInfo["msg"])+"\r\n"
    if result == "":
        result = "当前不存在未签到"
    else:
        if mailConfig["enabled"]:
            sendMail(mailConfig["smtp_server"],mailConfig["smtp_port"],mailConfig["from_addr"],mailConfig["from_pwd"],mailConfig["to_addr"],result)
        if serverChan["enabled"]:
            sendWechat(serverChan["SCKEY"],result)
    return result.replace("\r\n", " ")
def getMd5(str):
    md5=hashlib.md5()
    md5.update(str.encode("utf-8"))
    return md5.hexdigest()
def getDevice(equipmentModel,equipmentApiVersion,equipmentAppVersion,emit):
    tmp=getMd5(equipmentModel)+equipmentApiVersion
    tmp=getMd5(tmp)+equipmentAppVersion
    tmp=getMd5(tmp)+emit
    return getMd5(tmp)
def sendWechat(SCKEY,content):
    resultData={"text": "职教云签到结果", "desp": content}
    content.replace("\r\n", "\n\n")
    requests.post("https://sc.ftqq.com/" + SCKEY + ".send",data=resultData)
def sendMail(smtp_server,smtp_port,from_addr,from_pwd,to_addr,content):
    stmp=smtplib.SMTP_SSL(smtp_server,smtp_port)
    stmp.login(from_addr,from_pwd)
    message = MIMEText(content, "plain", "utf-8")
    message["From"] = Header("职教云自动签到系统", "utf-8")
    message["From"].append("<" + from_addr + ">", 'ascii')
    message["To"] = Header("用户", "utf-8")
    message["To"].append("<" + to_addr + ">", 'ascii')
    subject = "签到结果"
    message["Subject"] = Header(subject, 'utf-8')
    try:
        stmp.sendmail(from_addr, to_addr, message.as_string())
    except Exception as e:
        print ('邮件发送失败--' + str(e))
觉得文章不错的话,可以赞赏一下作者

alipay-256.png

含原创标签的文章未经允许不得转载 | 当前页面:专属我的味道 » 云课堂-智慧职教(职教云)自动签到云函数代码

评论 40

  1. 童话到此一游

    AI_童话 2020-03-23    回复
    • 按照你的视频设置好以后,关闭浏览器也能移动签到吗?

      仅此而已 2020-05-21    回复
      • 配置好腾讯云函数自动帮你签到,无需挂机

        专属味道 2020-05-21    回复
        • 啥时候更新?

          仅此而已 2020-05-25    回复
  2. 厉害厉害,感谢

    苏茨 2020-04-10    回复
  3. 直接在linux下运行源代码可行吗

    1 2020-04-14    回复
    • 把def auto_signin(event, context):改成if __name__ == '__main__':
      接着pip install requests就行了

      专属味道 2020-04-14    回复
      • 还要将return语句改成print

        专属味道 2020-04-14    回复
        • [root@cyber jiaoben]# nohup python3 -u zjy.py > log.log 2>&1
          [root@cyber jiaoben]# ls
          log.log zjy.py
          [root@cyber jiaoben]# cat log.log
          nohup: 忽略输入
          当前不存在未签到
          [root@cyber jiaoben]# ps
          PID TTY TIME CMD
          3030 pts/0 00:00:01 bash
          24409 pts/0 00:00:00 ps

          1 2020-04-15    回复
        • 不知道成功没有,后台看不见进程

          1 2020-04-15    回复
        • [root@cyber jiaoben]# python3 zjy.py
          File "zjy.py", line 48
          return result
          ^
          SyntaxError: 'return' outside function
          最后的return也要改成print吗

          1 2020-04-15    回复
          • 要的,print语句,记得带括号

            专属味道 2020-04-17    
      • 好的学习了

        1 2020-04-14    回复
  4. 这个代码现在还能用吗

    层久 2020-04-27    回复
  5. 配置smtp超时改成多少啊

    纤夫的爱 2020-04-28    回复
  6. 这代码是不是不是原来的代码啊?

    jiulo 2020-04-28    回复
    • 在原来的基础上更新了,修复了二维码签到不能签的问题

      专属味道 2020-04-28    回复
      • 可是现在有课也提示当前不存在签到啊

        jiulo 2020-04-29    回复
        • 我前天更新还特地测试过,可以签,我强调过了,只要签到成功过一次,就不会再提示签到成功了

          专属味道 2020-04-29    回复
          • 不是,如果签到成功的话那为什么微信和邮箱都没有通知啊,我按照教程填好邮箱和接入微信公众号了

            jiulo 2020-04-29    
          • 调整超时,server酱和邮箱同时设置,只要要签到成功,执行时间会比较久。你检查下有没有调用失败的

            专属味道 2020-04-29    
          • 可以了,只能设置一个通知,两个同时通知会调用失败

            jiulo 2020-04-30    
  7. 谢谢大佬创作分享。我刚才翻了一下日志,有点疑惑,请问cron表达式*/5 * 7-19 * * MON-FRI *其中的7-19指的是7:00-19:59吗?

    无言 2020-04-29    回复
  8. 我这返回数据显示\u 是要转中文吗?怎么转

    瓜娃子 2020-04-30    回复
  9. 楼主大大 求问QQ邮箱怎么设置 弄了一个多小时了 还是不会

    qwq 2020-05-13    回复
    • 代码中有示例的,QQ邮箱的授权码就是SMTP的密码

      专属味道 2020-05-13    回复
  10. 啊这今天更新了token验证

    Y 2020-05-25    回复
  11. 可以建一个QQ交流群吗

    woj 2020-05-26    回复
  12. 大佬 我想问下 为什么我更改了职教云密码之后 TX更改密码了 结果出现错误了

    学长 2020-05-26    回复
    • 职教云更新了api,自动签到失效了,后续更新

      专属味道 2020-05-26    回复
    • Traceback (most recent call last):

      File "/var/user/zjy.py", line 29, in auto_signin

      todayClassInfo=json.loads(todayClass.text)["dataList"]

      KeyError: 'dataList'

      学长 2020-05-26    回复
  13. 目前又失效了

    你猜猜 2020-07-04    回复
  14. 失效哥 ....又加了一个月的课程 蛮秀的...

    顾临 2020-07-08    回复
    • 登陆环节我测试没问题,获取今日课程环节也没问题,现在我没有可以签到的号,后续没办法更新了

      专属味道 2020-07-15    回复
      • 大佬 我这边账号 可以提供

        你猜猜 2020-07-19    回复
  15. 谢谢哥 继续更新 已赞助了一丢丢

    顾临 2020-07-29    回复