基于python实现的微信小程序“我在校园”每日自动健康打卡

image.png

前言

不管是在学校还是放假了

自从疫情出现以来

我们学校就规定每天必须健康打卡

时间长了就不想每天手动打卡了

想着抓一下请求每天自动打卡好了

计划开始

分析

说干就干

首先分析下目前的情况

我们学校用的是微信小程序“我在校园”进行打卡的

这导致了我一开始就不想干了

毕竟微信小程序给每个人分配的openID不一样

而且每个小程序获取到用户的openID也不一样

通俗点说就是用户在不同的小程序有不同的唯一的openID

最重要的是我拿不到这个openID

最后硬着头皮还是先去抓包

毕竟不管它怎么变总归要发送请求的

抓包

抓包有两种不同设备的方法

第一种是直接在手机上抓包

这对于Android7以上的用户是需要root权限的

所以这里就不介绍第一种方法了

推荐第二种方法就是电脑上抓包

登录需要打卡的微信windows版

启动你的抓包软件

我这里用的是Fiddler Web Debugger

开始捕获请求后打开windows微信的小程序“我的校园”

如果你是第一次使用或者删除了小程序之后再次使用的话

小程序应该会弹出一个授权提示

在你点击确定授权的时候的流程是这样的

image.png

从这里可以看出

作为用户是无法拿到自己在某个小程序的openID的

所以接下来我只能祈求这个小程序登录状态维持的时间够长

不然怎么弄都没有意义

如果有大佬有什么牛逼的办法能拿到openID的话

不妨让小弟学习学习

继续我们的试验

点击授权之后应该就获取到了我们需要的东西

接着停止Fiddler Web Debugger捕获

观察所有的请求

很明显这个请求就是我们需要的了

image.png

接下来就分析了下这个请求

image.png

请求的参数有code、encryptedData、iv、version、phone

用encodeURI解码后是这样子的

image.png

用base36解密试了下全是数字

看起来又好像是DES,AES之类的对称加密

整不了,要是有大佬会的能否向你请教一下

接着只能从获取到的token入手了

只是这样的话局限性很大了

究竟token的有效期是多久是个问题

我先进入打卡的界面看看有什么请求

image.png

查看了下请求返回如下

{
    "code": 0,
    "data": {
        "date": "2021-01-06",
        "country": "中国",
        "province": "海南省",
        "city": "XX市",
        "district": "XX区",
        "id": "XXXXXXXXXX",
        "titles": [{
            "healthOptions": [{
                "id": "0",
                "option": "无下列情况,身体健康",
                "select": 1,
                "seq": 0,
                "titleId": "1",
                "type": 0
            }, {
                "id": "1",
                "option": "近15日内居住或到过国内高风险、中风险地区",
                "select": 0,
                "seq": 1,
                "titleId": "1",
                "type": 1
            }, {
                "id": "2",
                "option": "最近15日内接触过新冠肺炎感染者",
                "select": 0,
                "seq": 2,
                "titleId": "1",
                "type": 1
            }, {
                "id": "3",
                "option": "发热(37.3度以上)、咳嗽、乏力、呼吸困难",
                "select": 0,
                "seq": 3,
                "titleId": "1",
                "type": 1
            }, {
                "id": "4",
                "option": "医学隔离",
                "select": 0,
                "seq": 4,
                "titleId": "1",
                "type": 1
            }, {
                "id": "5",
                "option": "疑似病例",
                "select": 0,
                "seq": 5,
                "titleId": "1",
                "type": 1
            }, {
                "id": "6",
                "option": "确诊病例",
                "select": 0,
                "seq": 6,
                "titleId": "1",
                "type": 1
            }, {
                "id": "631",
                "option": "近15日内在境外居住或到过境外",
                "select": 0,
                "seq": 7,
                "titleId": "1",
                "type": 1
            }],
            "id": "1",
            "seq": 0,
            "title": "关于新冠肺炎,你当前的状况是?",
            "type": 2
        }, {
            "answer": "36.8",
            "id": "28",
            "seq": 1,
            "title": "今日体温是多少(体温填报数字,请控制在35-42℃范围之间,保留1位小数点,例如37.2)",
            "type": 3
        }, {
            "healthOptions": [{
                "id": "175",
                "option": "绿码",
                "select": 1,
                "seq": 0,
                "titleId": "89",
                "type": 2
            }, {
                "id": "176",
                "option": "黄码",
                "select": 0,
                "seq": 1,
                "titleId": "89",
                "type": 2
            }, {
                "id": "177",
                "option": "红码",
                "select": 0,
                "seq": 2,
                "titleId": "89",
                "type": 2
            }],
            "id": "89",
            "seq": 2,
            "title": "你今天的“海南健康码”是什么状态?",
            "type": 1
        }]
    }
}

因为我今天已经打过卡了

所以在第二天我手动打卡试试看

填好相关的信息之后

提交打卡信息后看发送的请求以及返回的数据

image.png

可以看到用的是腾讯的定位api来进行定位的

不过这玩意不怎么准啊[狗头保命]

post发送的内容用urldecode解码后就是

answers=["0","36.8","0"]&latitude=20.044718&longitude=110.200001&country=中国&city=海口市&district=秀英区&province=海南省&township=长流镇&street=长滨东四街&areacode=460105

然后headers只包含了一个token

image.png

做到这里了那就简单了

我们自己发送一个post请求试试看

编写代码

我演示用的是python写的

伪装好header头部然后发送post请求就完事了

首先导入要用的两个模块

import json
import requests

接着伪造一个headers

headers_mini = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'host' : 'student.wozaixiaoyuan.com',
            'token' : 'XXXXXXXXXXXXXXXXXXXXXXXX'
        }

接着根据参数构造payload就可以了

payload = {
        'answers': '["0","36.8","0"]',
        'latitude': '20.044718',
        'longitude' : '110.200001',
        'country' : '中国',
        'city' : '海口市',
        'district' : '秀英区',
        'province' : '海南省'
    }

最后用requests自带的post发送请求并返回就完事了

r = requests.post(url=url, data=payload, headers=headers)
r.encoding = 'utf-8'

查看下返回的数据并没有出现错误

我又试了试在今日打了卡的情况下

如果用post再次请求与首次打卡返回的数据一模一样

不知道是官方在掩人耳目还是他们的程序员在划水

虽然略显粗糙但是这样就算完成了

但是局限还是在于官方对token设置的有效期

测试了下应该是72小时过期

所以如果安排上自动打卡的话

还是需要每三天手动抓包获取token

半个bug

测试的时候发现了一个小bug

在加载班级成员的时候

会发送一条请求并返回班级成员信息

每个班级有固定的唯一的id

image.png

返回的信息里面包含用户唯一id、姓名、学号、手机号

image.png

但是经过我的测试情况来看

不同班级之间似乎是不能获取到这些信息的

所以说只能看到自己本班的这些信息

虽然说是自己本班的信息

但是本该在数据库里待着的东西

却让它出现在前端就不应该

不知道什么时候能修复一下

吐槽就先到这吧

顺便插一嘴

可以用server酱来实现将打卡结果通过微信发送给你

如果下学期还有书读的话

会把刷步数的网站更完美的接入小米,以及增加乐心的接口

也许会上线每天全自动刷步数的功能

用户只需要填写好相关的信息并保存就完事了

还有就是二月的实验室的导航还没有做

实验室的内容目前有这些

刷步数

专治懒癌

你的手速快吗?

摸鱼神器

MD转HTML

但是却没有一个好看的导航页面

网上开源的都不是我喜欢的

所以决定自己写一个基于PHP的导航系统

不过由于时间都安排的满满的

还是等到下学期有时间的时候来吧

毕竟就目前而言我已经负债累累了

夜深了,睡觉吧

二月一寻

十八线无业游民,欢迎关注微信公众号1024黑~

2 Comments

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐