吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2347|回复: 33
收起左侧

[其他原创] 【支持多所高校】盛卡恩图书馆座位自动预约脚本

  [复制链接]
夸克逃逸 发表于 2023-3-6 09:28
本帖最后由 夸克逃逸 于 2023-3-8 08:56 编辑

更新一下:据盛卡恩官网介绍,该系统支持90余所高校,其中支持空间预约的学校包括:

【复旦大学研讨间 复旦大学座位预约  华东师范大学座位预约系统  六盘水师范学院座位预约系统 西南交通大学座位预约系统 新疆农业大学座位预约系统】

原来这个帖子是专门写华东师范大学的,后才猜测上面这些使用盛卡恩系统的也同样适用(当然只是猜测,没有实验证明,也不可能一一证明)。这个系统貌似包括了空间预约和通道闸机两个板块,我们学校是两个板块都用到了。官网上面介绍有很多学校用到了闸机,至于预约系统是否用的也是盛卡恩就不知道了。不过盛卡恩的系统界面基本一致:

2.3复旦大学座位预约_1600238487061.3复旦大学座位预约.jpg

无标题.png

大家可以看看自己图书馆的预约系统是不是类似的样子,如果是的话基本上确定是盛卡恩系统了。

好了开始介绍华师大的内卷生活:
华师大图书馆预约有一个规则:每天7点之后可以预约今天和明天两天的座位。换句话说,每天的座位都能够由前一天预约。我个人喜欢图书馆一楼某区域某些固定的座位,所以打算写一个脚本,免得每天早上7点定个闹钟只为了起床抢个座位,然后继续睡到8点。
老规矩,还是先抓包,用到了fiddler。具体来说就是电脑和手机连接wifi并保证处于同一局域网下。然后手机修改wifi的配置,手动配置主机地址和端口号,由fiddler代{过}{滤}理即可开始抓包。
亲测,在电脑上打开公众号网页没用,会检测到非手机端微信,所以只能用此方法。
好了,开始抓包。我一般都是先在手机上把关键的操作做一遍,然后一条一条的分析每个请求的作用。

011cf7050835b4f4236856af810deaf.jpg

  1. 第一个请求,从url可以看到请求函数为login,可以大胆推断这个请求就是用户登录。因此简单分析请求头、请求体和请求方法即可。这个不难,代码如下:

        // 用户登录
    public static HashMap<String, String> login() throws IOException {
        HashMap<String, String> map = new HashMap<>();
        map.put("status", "0");
        JSONObject obj = requestPost(BASE_URL + "/login", "from=mobile&password=" + PASSWORD + "&username=" + USERNAME);
        if (obj.getInteger("status") == 1) {
            JSONObject infoObj = obj.getJSONObject("data").getJSONObject("list");
            map.replace("status", "1");
            map.put("name", infoObj.getString("name"));
            map.put("card", infoObj.getString("card"));
            map.put("deptName", infoObj.getString("deptName"));
            map.put("gender", infoObj.getString("gender"));
            map.put("roleName", infoObj.getString("roleName"));
            map.put("accessToken", obj.getJSONObject("data").getJSONObject("_hash_").getString("access_token"));
        }
        return map;
    }

    注意,上述代码返回hashmap,是因为里面的参数在最后的预约请求中要用到。

  2. 第二个请求,请求函数是addUser,请求体里面也包含了学号等信息,但是域名不是学校的了,是一个第三方的域名,我查了一下,应该是上海盛卡恩智能系统有限公司。我猜测这个请求可能与闸机有关?没有测试过这个请求到底有没有实际作用,但是保险起见还是必须要加上的。因此,第二段代码为:

    // skalibrary添加用户信息
    public static Boolean addUser(String name, String card, String deptName, String gender, String roleName) throws IOException {
        String paramsStr = "openid=" + OPENID + "&username=" + USERNAME + "&password=" + PASSWORD + "&name=" + name + "&card=" + card + "&deptName=" + deptName + "&gender=" + gender + "&roleName=" + roleName + "&school=" + SCHOOL + "&schoolName=" + SCHOOL_NAME;
        JSONObject obj = requestPost(SKALIB_URL + "/addUser", paramsStr);
        return obj.getBoolean("status");
    }
  3. 第三个请求,请求函数是area,响应体正文中说明了是获取图书馆区域信息的。如果我们想要进一步写一个第三方的工具,用户注册,选择座位,我们帮用户自动预约的话,这个接口可以帮助用户自助选择座位。因为对于我来说,我想要预约的位置还是比较固定的,只需要固定位置的id即可预约,所以这个接口对于我来说暂时没有作用,这里不贴代码。完整代码可以github项目地址。

  4. 第四个请求,请求函数是space_days,由响应体的正文内容也可以看到,这个请求是获取可预约时间日期的。发送这个请求只会返回今明两天的日期,所以理论上来说,想要提前预约两天后的座位是不可能的了。最后的预约请求不会用到这个参数。

  5. 第五个请求,请求函数是space_time_buckets,从响应体正文来看,是获取可预约时间段。发送这个请求会返回当前请求时间-23:50。也就是说可预约时间段是此刻到晚上11点50。这个截止时间基本不会变,但是开始时间是此刻。这个请求返回的两个参数对于最后的预约是有用的,于是代码如下:

    // 获取可预约时间段
    // date : 预约日期 : 2023-03-05
    public static HashMap<String, String> getViableTime(String areaCode, String date) throws IOException {
        HashMap<String, String> map = new HashMap<>();
        map.put("status", "0");
        JSONObject obj = requestGet(BASE_URL + "/space_time_buckets?area=" + areaCode + "&day=" + date);
        if (obj.getInteger("status") == 1) {
            map.replace("status", "1");
            String segment = obj.getJSONObject("data").getJSONArray("list").getJSONObject(0).getString("id");
            String spaceId = obj.getJSONObject("data").getJSONArray("list").getJSONObject(0).getString("spaceId");
            map.put("segment", segment);
            map.put("spaceId", spaceId);
        }
        return map;
    }
  6. 第六个请求,请求函数是spaces_old,作用是获取座位预约信息,比如是否被预约等等。

  7. 第七个请求,请求函数是spaces,作用是获取空间信息。

  8. 第八个请求,请求路径是profile/books,根据返回内容来看,是获取用户的预约历史。只能传入token和用户名两个参数。因此估计这个请求只能够获取一定范围内的预约历史。如果能够获取更多预约历史的话,或许可以做一个可视化的展示等等。

  9. 第九个请求,终于来到了预约座位了。请求地址中需要包含座位id,所以之前的座位id需要提前保存。除此之外,还包括了很多其他的参数,代码如下:

    // 预约座位
    // type : 操作类型 : 1 : 预约座位
    // setId : 座位id : 6056
    public static HashMap<String, String> grabSeat(String accessToken, String type, String segment, String seatId) throws IOException {
        String paramStr = "access_token=" + accessToken + "&userid=" + USERNAME + "&type=" + type + "&id=" + seatId + "&segment=" + segment;
        JSONObject obj = requestPost(BASE_URL + "/spaces/" + seatId + "/book", paramStr);
        HashMap<String, String> map = new HashMap<>();
        map.put("status", "0");
        if (obj.getInteger("status") == 1 && obj.getString("msg").indexOf("预约成功") != -1) {
            map.replace("status", "1");
        }
        map.put("msg", obj.getString("msg"));
        return map;
    }
  10. 还有一个请求是很有用的,那就是登出用户。用户登陆之后获取一个token,有效期只有两三个小时。如果登录之后再登录会提示重复登陆。因此有必要先登出,再登录,每次请求都保证能够获取到最新的token。

  11. 最后说一下完整的预约流程:首先登出当前用户,然后登录获取token,再向skalibrary写入信息,然后请求预约时间,得到一些参数,再根据这些参数预约座位即可。代码如下:

    // 自动预约
    public static void autoGrabSeat() throws Exception {
        // 获取明天日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 1);
        String tomorrow = formatter.format(calendar.getTime());
        String content = "<div>预约位置:xxxx</div><div>位置id:" + SEAT_ID + "</div><div>预约日期:" + tomorrow + "</div>";
        // 开始预约
        // 先登出当前用户
        Boolean hasLogOut = removeUser();
        HashMap<String, String> map = login();
        if (map.get("status") == "0") {
            content = "<div>预约结果:预约失败</div>" + content + "<div>失败原因:初始登录失败</div>";
            SendEmailUtil.sendEmail(EMAIL, content);
            return;
        }
        Boolean addUser = addUser(map.get("name"), map.get("card"), map.get("deptName"), map.get("gender"), map.get("roleName"));
        if (!addUser) {
            content = "<div>预约结果:预约失败</div>" + content + "<div>失败原因:向skalibrary写入用户信息失败</div>";
            SendEmailUtil.sendEmail(EMAIL, content);
            return;
        }
        HashMap<String, String> map1 = getViableTime("40", tomorrow);
        if (map1.get("status") == "0") {
            content = "<div>预约结果:预约失败</div>" + content + "<div>失败原因:获取segement参数的过程中失败</div>";
            SendEmailUtil.sendEmail(EMAIL, content);
            return;
        }
        // 默认type为1
        HashMap<String, String> res = grabSeat(map.get("accessToken"), TYPE, map1.get("segment"), SEAT_ID);
        if (res.get("status") == "1") {
            content = "预约结果:预约成功!" + content;
        } else {
            content = "<div>预约结果:预约失败</div>" + content + "<div>失败原因:" + res.get("msg") + "</div>";
            SendEmailUtil.sendEmail(EMAIL, content);
            return;
        }
        SendEmailUtil.sendEmail(EMAIL, "<div>预约结果:预约成功!</div>" + content + "<div>莫等闲,白了少年头,空悲切!</div>");
    }

    在上述代码中,我还加入了发送邮件的功能。



3b8de614fcbd828576895109c71657e.jpg

说一下后续的拓展开发,有兴趣的ecnuer可以尝试:
1. 做一个定时签离的功能,能够在中午11点和下午5点准时临时签离,确保不会忘记签离。但是不要滥用这个功能,可能会导致临时签离之后不能准时从闸门进来导致违约。
2. 当前脚本只能针对某个固定的座位预约,应该足够了,为了防止有其他脚本,或者其他学生手快,建议多设置几个座位,自动预约的时候如果预约失败,可以预约其他设定好的座位。

请勿滥用,仅供交流学习~,使用时请遵守华东师范大学相关的规章制度,管理条例!
脚本地址:https://github.com/quarkape/ecnu-lib-auto-book.git

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
ll090822 + 1 + 1 热心回复!
s1711880582 + 1 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

cjzdjm 发表于 2023-3-6 10:21
有点厉害啦
 楼主| 夸克逃逸 发表于 2023-3-14 16:38
soyadokio 发表于 2023-3-14 13:25
感谢分享,分析部分还是很有意思的,可惜有点少

有些部分确实有意义,比如结合开发经验构建请求参数,能够获取所有的数据;根据checkout方法,构建checkin方法,从而实现签到等。不过主要功能还是蛮简单的。
s1711880582 发表于 2023-3-6 09:35
牛 昨天刚抓了个包 没分析明白 今天就有大佬做出来了
L的追梦人生 发表于 2023-3-6 09:40
有点厉害啦
yx159247 发表于 2023-3-6 09:51
感谢分享
orb001 发表于 2023-3-6 09:52
现在大学都这么内卷了吗?我记得当时我读大学的时候图书馆人很少的……不过可能是因为我读的不是华师大吧。
s1711880582 发表于 2023-3-6 09:59
作者能提供个Python的版本么?或者是Postmain调试的导出文件?
 楼主| 夸克逃逸 发表于 2023-3-6 10:09
orb001 发表于 2023-3-6 09:52
现在大学都这么内卷了吗?我记得当时我读大学的时候图书馆人很少的……不过可能是因为我读的不是华师大吧。

图书馆确实人很多,不过也还好,有些同学在玩手机。其次因为图书馆有空调,所以大部分同学还是愿意来图书馆的
www6130911 发表于 2023-3-6 10:12
感谢分享
 楼主| 夸克逃逸 发表于 2023-3-6 10:13
s1711880582 发表于 2023-3-6 09:59
作者能提供个Python的版本么?或者是Postmain调试的导出文件?

木有python版本,不过github上面有个计院的同学用python写了个,你可以搜搜看
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-21 21:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表