doupoa
一个不甘落后的热血青年!
Ping通途说

完美校园电费h5查询接口解析与应用

0. 前言

续上次微信端完美校园接口更新后,我就再也没有继续研究更多有关此类的接口了。直到今年有幸通过升本考试进入了新学校,入学期间正值酷暑,宿舍电费用的很快,而且宿舍内使用屏幕主机的就有三位。因此又重燃了我尝试爬取电量信息的动力。

因此在本文内我们将分析爬取过程及应用至飞书定时推送。

1. 解析接口

既然微信的接口无法用正常方法调用,那么能不能从其他方面入手?在网上搜寻相关资料时发现了有人公开了一个现成能用的查询接口,通过抓包方式抓取手机应用端内的接口请求,经过测试后发现该接口无需任何身份验证,仅需传入学号、学校编号以及宿舍号即可正常查询。

由于该接口是查询学号所绑定的房间号,返回了很多根本没绑定过的房间号和很多无效信息,因此我们来着手查询单个房间的电费。

https://doupoa.site/wp-content/uploads/2024/09/1727148563-image-edited-768x1024.png

先看一眼应该要获取的数据,在这个页面应该能查询到“设备名称”,“设备编号”、“今日用电”、“剩余电量”、以及每日的使用趋势。

关于APP抓包的操作在本文不再阐述,请自行搜索相关教程或返回页头的文章查阅。

通过抓包与分析,我们获得了最终的请求接口【https://xqh5.17wanxiao.com/smartWaterAndElectricityService/SWAEServlet】。使用POST方式请求,该接口能够获取上图所示的所有信息。

在这里不得不吐槽一句,第一次见这么新奇的接口请求方式!

居然还能把请求参数用json的方式塞url里并且用的POST方式请求,POST了个寂寞..怪不得能被脱裤..

https://doupoa.site/wp-content/uploads/2024/09/1727149325-image-1024x441.png

如上图所示,需要传入的参数有宿舍号、学号或工号。填补以上参数后在apifox中进行测试,不出意外的话数据获取成功。我将本文中所用到的所有接口存入了APIfox中,有需要的可以在以下链接查阅。其中宿舍号需要先通过“查询账号所绑定的房间号”去获取,学校编号也可以通过以下链接查找。

Apifox - 完美校园智能水电API

2. 定时查询并推送

推送平台我选择飞书,这是我工作时公司使用的办公软件,经过一段时间自己使用过后发现确实非常实用,做文档之类的非常方便,并且个人用户都能够自定义机器人。其他社交软件基本都不支持编写机器人推送,或者限制很多,无法做到主动推送或仅限企业可用。如果你有更好的平台欢迎在下方评论区分享!

老规矩先上脚本:

import requests
import datetime
import json
import hashlib
import base64
import hmac
from apscheduler.schedulers.background import BlockingScheduler
import sys

webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxx" # 填入自己的Webhook地址
sign = "xxxx" # 填入自己的校验密钥

roomverify = "xxxx" # 填入要查询的房间号
account = "xxxx" # 填入你的学号或工号
customercode = "xxxx" # 填入你的学校编号


def gen_sign(timestamp, secret):
    # 拼接timestamp和secret
    string_to_sign = '{}\n{}'.format(timestamp, secret)
    hmac_code = hmac.new(string_to_sign.encode("utf-8"),
                         digestmod=hashlib.sha256).digest()
    # 对结果进行base64处理
    sign = base64.b64encode(hmac_code).decode('utf-8')
    return sign


def doPost(elements: list):
    timestamp = int(datetime.datetime.timestamp(datetime.datetime.now()))
    with requests.session() as s:
        s.post(webhook, json={
            "timestamp": timestamp,
            "sign": gen_sign(timestamp, sign),
            "msg_type": "interactive",
            "card": {
                "elements": elements,
                "header": {
                    "title": {
                        "content": "今日电费推送",
                        "tag": "plain_text"
                    }
                }
            }
        })


def main(url):
    ts = datetime.datetime.now().strftime("%Y%m%d%H%M%S000")
    param = {"cmd": "h5_getstuindexpage", "roomverify": roomverify,
             "account": account, "timestamp": ts}
    url = f"https://xqh5.17wanxiao.com/smartWaterAndElectricityService/SWAEServlet?param={json.dumps(
        param)}&customercode={customercode}&method=h5_getstuindexpage&command=JBSWaterElecService"

    payload = {}
    headers = {
        "User-Agent": "Mozilla/5.0 (Linux; Android 14; REP-AN00 Build/HONORREP-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/127.0.6533.103 Mobile Safari/537.36 Wanxiao/5.8.6",
        "sec-ch-ua-platform": "Android",
        "Accept": "*/*",
        "Origin": "https://xqh5.17wanxiao.com",
        "X-Requested-With": "com.newcapec.mobile.ncp",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Dest": "empty",
        "Referer": "https://xqh5.17wanxiao.com/userwaterelecmini/index.html",
        "Accept-Language": "zh-CN,zh;q=0.9,en-CN;q=0.8,en-US;q=0.7,en;q=0.6",
        "Set-Cookie": "SERVERID=7abd666da76fadf6bd7f0a8acd3e2ff1|1725968099|1725968080;Path=/",
        "content-type": "application/x-www-form-urlencoded"
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    data = response.json()
    body = json.loads(data["body"])
    weekuse = ""
    weekuselist = body["modlist"][0]["weekuselist"]
    for i in range(len(weekuselist), 0, -1):
        weekuse += f"**{weekuselist[i-1]['daydate']}({weekuselist[i-1]['weekday']})**:{
            weekuselist[i-1]['dayuse']} 度 \n"

    data = {
        "tag": "div",
        "text": {
            "content": f"""**宿舍号**:  {body["roomfullname"]}
**设备MAC**: {body["modlist"][0]["mac"]}

**剩余电量**: {body["modlist"][0]['odd']} 度

**周用量**:
{weekuse}
    """,
            "tag": "lark_md"
        }
    }

    doPost([data])


if __name__ == "__main__":
    if len(sys.argv) >= 2:
        if sys.argv[1] == "once":
            print("Only execute once.")
            try:
                if sys.argv[2] == "today":
                    main(today=True)
            except:
                print("Error Argvs")
                exit()
            main()
    else:
        print("The task has been initiated and runs at 18:00 every day.")
        scheduler = BlockingScheduler()
        scheduler.add_job(main, 'cron', hour=18)  # 每天18点运行
        scheduler.start()

以上脚本实际上就对接口查询,解析,最后推送结果。效果如下:

https://doupoa.site/wp-content/uploads/2024/09/1727150516-e7378b0f80c72247bf4d92f9e99d6b9-945x1024.jpg

关于飞书及机器人设置:

  1. 推荐在群聊内使用,即使只有一个人也能拉群。个人向机器人(飞书机器人助手)似乎已经停止维护,使用时会出现一些莫名的问题(如无权限)。
  2. 自己创建的,只有自己一个人的群聊默认为内部群,此时将群聊分享给朋友同学是无法加入的。需要先添加好友后手动拉入群聊后该群才会变为外部群,此时再分享入群二维码。
  3. 群机器人拉取方式:群 - 右上三点 - 设置 - 群机器人 - 添加机器人 - 自定义机器人,填写相关信息,安全设置推荐使用签名校验。(脚本使用签名校验,即使当前设置不勾选签名校验依然能正常请求。)
  4. 记得分别复制机器人创建框内的Webhook地址Sign签名密钥到脚本中,两者请勿向外泄露。

赞赏

doupoa

文章作者

诶嘿

发表回复

textsms
account_circle
email

Ping通途说

完美校园电费h5查询接口解析与应用
0. 前言 续上次微信端完美校园接口更新后,我就再也没有继续研究更多有关此类的接口了。直到今年有幸通过升本考试进入了新学校,入学期间正值酷暑,宿舍电费用的很快,而且宿舍内使用…
扫描二维码继续阅读
2024-09-24

Optimized by WPJAM Basic