2025年9月20日星期六

班级魔方任务脚本

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/DT4XYh若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/DT4XYh

若失效,可用地址

https://www.aliyun.com/activity/wuying/dj?source=5176.29345612&userCode=49hts92d

腾讯云:

https://curl.qcloud.com/wJpWmSfU

若失效,可用地址

https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console

华为云

https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

import randomimport requestsimport reimport timeimport osfrom bs4 import BeautifulSoupimport jsonimport schedulefrom datetime import datetimeimport logging
# 获取当前目录current_directory = os.getcwd()file_name = "config.json"file_path = os.path.join(current_directory, file_name)

# 检查文件是否存在if not os.path.exists(file_path):    # 定义默认的 JSON 数据    default_config = {        "class"""# 班级ID        "lat"""# 纬度        "lng"""# 经度        "acc"""# 海拔        "time"0# 等待时间(已弃用)        "cookie"""# 用户令牌        "scheduletime"""# 定时任务        "pushplus"""# pushpush推送令牌        "debug"False# 调试模式        "configLock"False #配置编辑状态,    }    # 文件不存在,创建并写入默认数据    with open(file_path, "w"as file:        json.dump(default_config, file, indent=4)    print("----------初始化----------")    print(f"文件 {file_name} 不存在,已创建并填充默认数据。")
# 读取外部 JSON 文件中的数据with open(file_path, 'r'as file:    json_data = json.load(file)    debug = json_data["debug"]
    # 判断是否首次使用或解除配置锁定    if not json_data['configLock']:        ClassID = input("请输入班级ID:")        X = input("请输入纬度(X):")        Y = input("请输入经度(Y):")        ACC = input("请输入海拔:")        Cookies = []        print("请输入你的Cookie,输入空行结束,支持用户备注格式如下")        print("username=<备注>;remember....<魔方Cookie>")        while True:            cookie = input("Cookie: ")            if not cookie:                break            Cookies.append(cookie)        print("----------配置定时任务(可选)----------")        print("格式为00:00,例如1:30要填写为01:30!不设置定时请留空")        print("Tip:请注意以上格式并使用英文符号":"不要使用中文符号":"")        scheduletime = input("请输入签到时间:")        if scheduletime=="":            print("您未填写签到时间,未启用定时签到,启动即开始签到")        print("----------远程推送----------")        pushtoken = input("(未适配新版多人签到,如果是多人签到建议不使用)\n请输入pushplus推送密钥,不需要请留空:")
        print("配置完成,您的信息将写入json文件,下次使用将直接从json文件导入")        # 2. 修改数据        json_data["class"] = ClassID        json_data["lat"] = X        json_data["lng"] = Y        json_data["acc"] = ACC        json_data["cookie"] = Cookies        json_data["scheduletime"] = scheduletime        json_data["pushplus"] = pushtoken        json_data["configLock"] = True        # 3. 写回JSON文件        with open(file_path, "w"as file:            json.dump(json_data, file, indent=4# indent 设置缩进为4个空格        print("数据已保存到"+current_directory+"下的data.json中。")    else:        print("----------欢迎回来----------")        ClassID = json_data["class"]        X = json_data["lat"]        Y = json_data["lng"]        ACC = json_data["acc"]        Cookies = json_data["cookie"]        scheduletime = json_data["scheduletime"]        pushtoken = json_data["pushplus"]        print("配置已读取")        if scheduletime=="":            print("当前签到模式为:手动,即将开始签到")        else:            print("当前签到模式为:自动,启动定时任务")    print("----------信息----------")    print("班级ID:" + ClassID)    print("纬度:" + X)    print("经度:" + Y)    print("海拔:" + ACC)    # print("检索间隔:" + str(SearchTime))    print("Cookie数量:" + str(len(Cookies)))    print("定时:" + scheduletime)    print("通知token:" + pushtoken)    if debug:print("Debug:" + str(debug))    print("---------------------")
def printLog(type, message):    if debug:        if type == "info":            logger.info(message)        elif type == "warning":            logger.warning(message)        elif type == "error":            logger.error(message)        elif type == "critical":            logger.critical(message)        else:            logger.info(message)
if debug:    # 创建 logger    logger = logging.getLogger()    logger.setLevel(logging.INFO)    # 创建文件处理器并设置编码为 UTF-8    file_handler = logging.FileHandler('AutoCheckBJMF.log', encoding='utf-8')    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')    file_handler.setFormatter(formatter)    # 将处理器添加到 logger    logger.addHandler(file_handler)    printLog("info""已启动Debug")print("一切就绪,程序开始执行\\^o^/")

# 随机经纬,用于多人签到定位偏移def modify_decimal_part(num):    num = float(num)    # print(num)    # 将浮点数转换为字符串    num_str = f"{num:.8f}"  # 确保有足够的小数位数    # 找到小数点的位置    decimal_index = num_str.find('.')    # 提取小数点后4到6位    decimal_part = num_str[decimal_index + 4:decimal_index + 9]    # 将提取的小数部分转换为整数    decimal_value = int(decimal_part)    # 生成一个在-150到150范围的随机整数    random_offset = random.randint(-1500015000)    # 计算新的小数部分    new_decimal_value = decimal_value + random_offset    new_decimal_value = abs(new_decimal_value)    # 将新的小数部分转换为字符串,并确保它有3位    new_decimal_str = f"{new_decimal_value:05d}"    # 拼接回原浮点数    new_num_str = num_str[:decimal_index + 4] + new_decimal_str + num_str[decimal_index + 9:]    # 将新的字符串转换回浮点数    new_num = float(new_num_str)
    return new_num
def thisTime(hour,minute):    # 指定的小时和分钟,这里示例为21:50,你可以按需修改    target_hour,target_minute = hour,minute
    # while True:    # 获取当前时间的时间戳    current_time_stamp = time.time()    # 获取当前时间的结构体    current_time_struct = time.localtime(current_time_stamp)
    # 获取当天的日期部分,构造一个新的时间结构体,用于设置指定时间    today_date = time.strftime("%Y-%m-%d", current_time_struct)    target_time_struct = time.strptime(today_date + " " + str(target_hour) + ":" + str(target_minute) + ":00""%Y-%m-%d %H:%M:%S")    target_time_stamp = time.mktime(target_time_struct)
    if target_time_stamp < current_time_stamp:        # 如果目标时间已经小于当前时间,说明今天的时间已经过了,那就设置为明天的同样时间        target_time_stamp += 24 * 3600
    # 计算时间差(单位为秒)    remaining_seconds_main = int(target_time_stamp - current_time_stamp)    # 计算剩余小时数    remaining_hours = remaining_seconds_main // 3600    remaining_seconds = remaining_seconds_main % 3600    # 计算剩余分钟数    remaining_minutes = remaining_seconds // 60    remaining_seconds %= 60
    # 格式化当前时间结构体为字符串    current_time = time.strftime("%Y-%m-%d %H:%M", current_time_struct)
    # 区分剩余时间的显示逻辑,以优化终端内容的显示阅读体验    if remaining_seconds_main < 300:        # 如果剩余时间小于5分钟则每秒刷新        print("\r当前时间:{},距离下次任务执行{}:{} 还剩{}分钟{}秒\t\t".format(            current_time, target_hour, target_minute, remaining_minutes, remaining_seconds), end="")        time.sleep(1)    else:        # 如果剩余时间大于5分钟则每分钟刷新        print("\r当前时间:{},距离下次任务执行{}:{} 还剩{}小时{}分钟\t\t".format(            current_time, target_hour, target_minute, remaining_hours, remaining_minutes), end="")        time.sleep(60)
def qiandao(theCookies):    # title = '班级魔法自动签到任务'  # 改成你要的标题内容    url = 'http://k8n.cn/student/course/' + ClassID + '/punchs'    errorCookie = []    nullCookie = 0    # 多用户检测签到    for uid in range(0,len(theCookies)):        onlyCookie = theCookies[uid]
        # 使用正则表达式提取目标字符串 - 用户备注        pattern = r'username=[^;]+'        result = re.search(pattern, onlyCookie)
        if result:            username_string = " <%s>"%result.group(0).split("=")[1]        else:            username_string = ""
        # 用户信息显示与5秒冷却        print("☆☆☆☆☆ 用户UID:%d%s 即将签到 ☆☆☆☆☆"%(uid+1,username_string),end="")        time.sleep(1#暂停5秒后进行签到        print("\r★☆☆☆☆ 用户UID:%d%s 即将签到 ☆☆☆☆★"%(uid+1,username_string),end="")        time.sleep(1)        print("\r★★☆☆☆ 用户UID:%d%s 即将签到 ☆☆☆★★"%(uid+1,username_string),end="")        time.sleep(1)        print("\r★★★☆☆ 用户UID:%d%s 即将签到 ☆☆★★★"%(uid+1,username_string),end="")        time.sleep(1)        print("\r★★★★☆ 用户UID:%d%s 即将签到 ☆★★★★"%(uid+1,username_string),end="")        time.sleep(1)        print("\r★★★★★ 用户UID:%d%s 开始签到 ★★★★★"%(uid+1,username_string))
        # 使用正则表达式提取目标字符串 - Cookie        pattern = r'remember_student_59ba36addc2b2f9401580f014c7f58ea4e30989d=[^;]+'        result = re.search(pattern, onlyCookie)
        if result:            extracted_string = result.group(0)            if debug:                print(extracted_string)            headers = {                'User-Agent''Mozilla/5.0 (Linux; Android 9; AKT-AK47 Build/USER-AK47; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 XWEB/1160065 MMWEBSDK/20231202 MMWEBID/1136 MicroMessenger/8.0.47.2560(0x28002F35) WeChat/arm64 Weixin NetType/4G Language/zh_CN ABI/arm64',                'Accept''text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/wxpic,image/tpg,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',                'X-Requested-With''com.tencent.mm',                'Referer''http://k8n.cn/student/course/' + ClassID,                'Accept-Encoding''gzip, deflate',                'Accept-Language''zh-CN,zh-SG;q=0.9,zh;q=0.8,en-SG;q=0.7,en-US;q=0.6,en;q=0.5',                'Cookie': extracted_string            }
            response = requests.get(url, headers=headers)            print("响应:", response)
            # 创建 Beautiful Soup 对象解析 HTML            soup = BeautifulSoup(response.text, 'html.parser')
            title_tag = soup.find('title')
            if debug:                print("★☆★")                print(soup)                print("===")                print(title_tag)                print("★☆★")
            if title_tag and "出错" not in title_tag.text:                # 使用正则表达式从 HTML 文本中提取所有 punch_gps() 中的数字                pattern = re.compile(r'punch_gps\((\d+)\)')                matches = pattern.findall(response.text)                print("找到GPS定位签到:", matches)                pattern2 = re.compile(r'punchcard_(\d+)')                matches2 = pattern2.findall(response.text)                print("找到扫码签到:", matches2)                matches.extend(matches2)                if matches:                    for match in matches:                        url1 = "http://k8n.cn/student/punchs/course/" + ClassID + "/" + match                        newX = modify_decimal_part(X)                        newY = modify_decimal_part(Y)                        payload = {                            'id'match,                            'lat': newX,                            'lng': newY,                            'acc': ACC,  #未知,可能是高度                            'res''',  #拍照签到                            'gps_addr'''  #未知,抓取时该函数为空                        }
                        response = requests.post(url1, headers=headers, data=payload)                        print("签到请求已发送: 签到ID[%s] 签到定位[%s,%s] 签到海拔[%s]"%(match, newX, newY, ACC))                        printLog("info""用户UID[%d%s] | 签到请求已发送: 签到ID[%s] 签到定位[%s,%s] 签到海拔[%s]"%(uid+1, username_string, match, newX, newY, ACC))
                        if response.status_code == 200:                            print("请求成功,响应:", response)
                            # 解析响应的 HTML 内容                            soup_response = BeautifulSoup(response.text, 'html.parser')                            # h1_tag = soup_response.find('h1')                            div_tag = soup_response.find('div'id='title')
                            if debug:                                print("★☆★")                                print(soup_response)                                print("===")                                print(div_tag)                                print("★☆★")
                            if div_tag:                                h1_text = div_tag.text                                print(h1_text)                                printLog("info""用户UID[%d%s] | %s"%(uid+1, username_string, h1_text))                                # encoding:utf-8                                if pushtoken != "" and h1_text== "签到成功":                                    url = 'http://www.pushplus.plus/send?token=' + pushtoken + '&title=' + "班级魔法自动签到任务" + '&content=' + h1_text  # 不使用请注释                                    requests.get(url)  # 不使用请注释                                continue  # 返回到查找进行中的签到循环                            else:                                print("未找到 <h1> 标签,可能存在错误")                                printLog("info""用户UID[%d%s] | 未找到 <h1> 标签,可能存在错误或签到成功"%(uid+1, username_string))                        else:                            print("请求失败,状态码:", response.status_code)                            printLog("error""用户UID[%d%s] | 请求失败,状态码: %d"%(uid+1, username_string, response.status_code))                            print("将本Cookie加入重试队列")                            errorCookie.append(onlyCookie)                else:                    print("未找到在进行的签到")            else:                print("登录状态异常,将本Cookie加入重试队列")                printLog("error""用户UID[%d%s] | 登录状态异常"%(uid+1, username_string))                errorCookie.append(onlyCookie)        else:            nullCookie += 1            print("未找到匹配的字符串,检查Cookie是否错误!")    return errorCookie, nullCookiedef job():    current_time = datetime.now()    print("\n进入检索,当前时间为:", current_time)
    errorCookie,nullCookie = qiandao(Cookies)    if len(errorCookie)>0:        print("检测到有Cookie签到失败,等待5分钟后启动一次重试队列")        time.sleep(300)        errorCookie = qiandao(errorCookie)        if len(errorCookie)>0:            print("检测到仍然有Cookie签到失败,等待15分钟后最后启动一次重试队列")            time.sleep(900)            errorCookie = qiandao(errorCookie)            if len(errorCookie)>0:                print("!!!  检测到仍然有Cookie签到失败,请检查Cookie是否过期或网络异常  !!!")    elif nullCookie>0:        print("!!! 本次签到存在异常,请检查Cookie是否均已正常配置 !!!")    else:        print("签到成功")
    print("分割线")
    if scheduletime:        print("本次签到结束,等待设定的时间%s到达☆\n"%scheduletime)
if (scheduletime != ""):    print("等待设定时间" + scheduletime + "到达☆")    # 设置定时任务,在每天的早上8点触发    schedule.every().day.at(scheduletime).do(job)    # 格式化时间    hour,minute = scheduletime.split(":")
    while True:        schedule.run_pending()        thisTime(hour,minute) # 倒计时else:    job()    input("手动签到已结束,敲击回车关闭窗口☆~")

解析

该脚本为班级魔方自动签到脚本,主要作用为:

  • 首次运行交互式生成并锁定 config.json(班级ID、经纬度、海拔、Cookies、定时等);

  • 读取配置后,单次或定时扫描当前班级课程的进行中签到(GPS/扫码);

  • 为每个 Cookie(可多人)自动提交签到(带经纬度微偏移);

  • 结果解析与失败重试(5 分钟与 15 分钟两轮);

  • 可选 pushplus 成功通知;

  • 支持 debug 日志(写入 AutoCheckBJMF.log)。

主要方法的作用

  • 配置初始化与读取

    • 创建/读取 config.json,首启交互填写并 configLock 锁定;之后直接载入。

    • 支持多账户 Cookies;可设置定时 scheduletime 与 pushplus token。

  • printLog(type, message)

    • 在 debug=True 时,把不同级别日志写到 AutoCheckBJMF.log

  • modify_decimal_part(num)

    • 对输入的经纬度数值随机扰动小数第4–8位(±15000 量级的五位微调),实现多人签到时的定位微偏移,避免定位完全一致。

  • thisTime(hour, minute)

    • 定时模式下的倒计时输出:距下次执行小于 5 分钟按秒刷新,否则按分钟刷新。

  • qiandao(theCookies)

    • 抓取 punch_gps(<id>)(GPS签到)与 punchcard_<id>(扫码签到);

    • 生成随机偏移后的经纬度,POST 提交签到;

    • 解析返回页 <div id="title"> 展示结果文本(如"签到成功");

    • 如开启 pushplus 且成功则推送;

    • 核心签到流程(对传入的 Cookie 列表逐个执行):

    • 返回 (errorCookie, nullCookie) 给上层处理。

    1. 从 remember_student_... 中提取有效 Cookie;显示备注 username=...(若有)。

    2. 访问 http://k8n.cn/student/course/{ClassID}/punchs 获取签到页 HTML。

    3. 解析 HTML(BeautifulSoup):

    4. 对每个签到 ID:

    5. 失败或登录异常的 Cookie 放入重试队列返回;统计 Cookie 缺失/错误。

  • job()

    • 调用 qiandao(Cookies)

    • 对失败 Cookie 分两轮重试(5 分钟与 15 分钟后各一次);

    • 输出总结:圆满成功 / 存在异常 / 仍有失败提示。

    • 定时模式下打印等待提示。

    • 一次完整的扫描+签到任务:

  • 定时与入口

    • 若 scheduletime 非空:

      schedule.every().day.at(scheduletime).do(job)

      循环 schedule.run_pending() 并用 thisTime() 倒计时;

    • 否则直接执行一次 job(),并等待回车退出。

  • 其他要点

    • 多用户Cookies 为列表,逐个执行并显示"UID+备注"。

    • 容错:HTML 结构变化/登录异常会落入重试或提示。

    • 网络:全部基于 requests;页面解析用 BeautifulSoup

    • 通知:可选 pushplus 成功通知(仅对"签到成功"触发)。


注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>

没有评论:

发表评论

3个国家都认可的抄书平台,一天1000+,一单一结,居家就能做!

老听有人说抄书就能赚钱,甚至还吹嘘一天三五十,听着挺心动的。 今天咱们就来扒一扒,到底是真是假,有没有传的那么神。 我深挖了一下, 有一些确实是骗子,但是有真实的,有正规的,我就在做,一天能赚个几十上百块。 下面就挑3个比较正规的类型给大家说一下,顺便谈一下我的看法。 一、什...