某某儿科医院APP登陆与抢票分享

news2024/9/20 20:52:33

1. 背景

近期到了暑假,儿保的票是越来越难抢了。卡着点也不能刷得到,有天偶然打开发现某个热门门诊突然有一个票,然后就帮人挂到了。琢磨一下,这种不是秒杀的抢票,如果能把所有取消的捡漏刷到,其实问题也不算大。毕竟这软件的放票规则是一周前就放了,一周内总是有人会偶尔取消一把的。

心随所至,动手就干。一般这种医院机构的APP,都是外包实现的,而且费用预算有限,承接方甚至会逐层转包,最终能开发者能拿到的费用不会很高。费用低到一定程度的时候,他们只会考虑功能实现,不会考虑太多安全性问题。应该简单的抢票不会太难。

2. 分析

大多数的APP小程序的架构都是使用前后端分离的架构,也就是说前端界面由前端开发,后端数据由后端开发。这样的架构方便实现跨平台,APP,WEB,小程序都可以公用一套后端系统,前端代码使用的跨平台工具的话,前端也只需要实现一套代码,然后在不同的平台上发布即可。

一个很有代表性的外包前端开发利器就是UniAPP,可以实现一套前端代码,实现多端发布 iOSAndroidH5各种小程序。前端问题解决后,这里只需要把对应的与后端交互接口用Restful的方式进行简单封装,即可完成业务开发。

这里后端使用任何一种WEB APP即可实现,比如Node.jsPHPJavaPython等等,不要太多。

2.1 猜想验证

某某儿科医院这个APP在 App Store 中可以下载,这里我们可以利用 macOS 也可以安装 iPhone 应用的特点,在安装后,直接显示包内容,从而观察到APP的实现,从而大体验证我们的分析猜想是不是对的。

第一层目录中有 Pandora 文件夹的时候,熟悉 UniAPP 开发的小伙伴应该知道的大差不差了,再进行展开后,看到了UniAPP的各种前缀文件,没的跑了。

在这里插入图片描述

而且这个开发团队还是懂得前后端分离的,名字起的都太具有特点了,app-service.jsapp-view.js。敢情好,其他的js也不用看了呗,前端界面的代码就是view,和后端交互的接口类不就是 app-service.js了。谢谢了。

2.2 总结

分析到这里,大体感觉应该大差不差了。接受外包任务的团队为了最低成本的实现多端发布,并且也不会有很多繁复的任务,的确和我们最开始的猜想很近似。那么我们只要通过把 Restful的内容理解清楚,知道他们怎么组包的,就知道怎么模拟APP抢票的过程了。

3. 动手

既然要了解 APP后端服务器 怎么交互,那么就一定要抓包,电脑上抓包都知道用 Wireshark 或者 tcpdump,手机咋抓包呢? 这里iOS一般推荐这个 Stream 免费好用。

在这里插入图片描述

这里抓包细节就不展开了,偏离主题了。直接展现抓包结果。

在这里插入图片描述
在这里插入图片描述

好家伙,猜到了前后端,但没猜到这里的所有实现居然都是明文,请求头,请求体都是明文。咳咳咳。是不是我搞错了。这里重放一下请求。

#### 登陆

POST https://mobiles.zhicall.cn/mobile-web/mobile/patient/get/familyMembers/true/_这里是5个大写A到F的字符,为了安全就不展示了/10356 HTTP/1.1

Host: mobiles.zhicall.cn
Data-Sign: ab421bfd4003f09c63a6cdb344b2192a
Accept: */*
from: 0
hospitalId: 10356
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh-Hans;q=0.9
token: 13456789123  
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
User-Agent: iPhone14,5(iOS/16.5.1) Uninview(Uninview/1.0.0) Weex/0.26.0 1125x2436
Connection: keep-alive

hospitalId=10356&agencyId=10356&from=0

好家伙,回了包,直接把身份证给晒出来了,有些甚至父母信息,家庭地址都有。

HTTP/1.1 200 OK
Date: Sun, 30 Jul 2023 13:26:33 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, DELETE
Access-Control-Allow-Headers: Origin,DNT,X-CustomHeader,X-Access-Token,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Data-Sign

{
  "data": [
    {
      "accountId": "_为了安全不晒",
      "address": "金华东阳xxxxxxxxxx为了安全不晒",
      "aesPatientId": "为了安全不晒",
      "age": 12,
      "birthday": "2011-07-23",
      "hospitalId": 10356,
      "id": 266602,
      "idCard": "3307为了安全不晒2",
      "medicalCardId": 163511,
      "medicalCardNo": "61691879",
      "medicalCardType": "省一卡通",
      "medicalCardValid": true,
      "medicalCards": [
        {
          "aesPatientId": "为了安全不晒",
          "createTime": "2019-01-28 13:49:19",
          "hospitalId": 10356,
          "id": 163511,
          "medicalCardNo": "61691879",
          "medicalCardType": "省一卡通",
          "medicalCardTypeId": 103568,
          "medicalCardValid": true,
          "mid": "EBGAEE",
          "name": "高为了安全不晒",
          "patientId": 266602,
          "updateTime": "2019-01-28 13:49:19"
        }
      ],
      "mobileNo": "138为了安全不晒",
      "name": "高为了安全不晒",
      "paperName": "身份证",
      "paperNo": "330为了安全不晒",
      "paperType": "IDENTITY_CARD",
      "patientType": 0,
      "sex": "FEMALE"
    }
  ],
  "success": true
}

细想一看不对,我都没输入任何密码或者手机验证码怎么就登陆了?

看了看这里的请求,说白了这里只有用户名,没有任何密码。只要你知道自己对应的用户名,那么你就可以登陆了。

虽然这个结果是真的有点离谱,但事实你的小孩还有你的信息就是泄露的这么彻彻底底。

那我们继续看看怎么刷票吧,以后这种APP上信息少填点总是没错的。

3.1 重放调试

这里不展开具体寻找请求报文的过程,大体思路就是打开APP,依次点抢票的几个按钮,每个按钮对应都会有一个或者多个请求链接,操作完后切换到 Stream 中去在对应域名中查找请求包的URL和内容,查看对应回复大概能猜到。

这里直接晒最关键的看是否有余票的请求链接。

请求报文如下:


POST https://mobiles.zhicall.cn/mobile-web/mobile/schedule/new/10361/dept/1037800243/info HTTP/1.1

Host: mobiles.zhicall.cn
Data-Sign: d9e69844f90031d106b5e6a28879062d
Accept: */*
from: 0
hospitalId: 10361
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh-Hans;q=0.9
Content-Type: application/x-www-form-urlencoded
Content-Length: 89
User-Agent: iPhone14,5(iOS/16.5.1) Uninview(Uninview/1.0.0) Weex/0.26.0 1125x2436
Connection: keep-alive

fetchType=SCHEDULE_REALTIME&expertType=DEPT_COMMON&hospitalId=10361&agencyId=10361&from=0

对应的回复报文如下:

HTTP/1.1 200 OK
Date: Sun, 30 Jul 2023 13:43:30 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, DELETE
Access-Control-Allow-Headers: Origin,DNT,X-CustomHeader,X-Access-Token,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Data-Sign

{
  "data": {
    "childDeptList": [],
    "doctors": [],
    "id": 1037800243,
    "leftNum": 1,
    "name": "(内分泌科)生长发育门诊",
    "regNewScheduleVOList": [
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-07-31",
        "regTime": "MORNING",
        "remark": "已满",
        "rest": false,
        "scheduleId": "480556:A",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周一"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-07-31",
        "regTime": "AFTERNOON",
        "remark": "已满",
        "rest": false,
        "scheduleId": "480590:P",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周一"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-01",
        "regTime": "MORNING",
        "remark": "已满",
        "rest": false,
        "scheduleId": "481037:A",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周二"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-01",
        "regTime": "AFTERNOON",
        "remark": "已满",
        "rest": false,
        "scheduleId": "481353:P",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周二"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-02",
        "regTime": "MORNING",
        "remark": "已满",
        "rest": false,
        "scheduleId": "481752:A",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周三"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-02",
        "regTime": "AFTERNOON",
        "remark": "已满",
        "rest": false,
        "scheduleId": "481850:P",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周三"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-03",
        "regTime": "MORNING",
        "remark": "已满",
        "rest": false,
        "scheduleId": "482186:A",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周四"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-03",
        "regTime": "AFTERNOON",
        "remark": "已满",
        "rest": false,
        "scheduleId": "482142:P",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周四"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-04",
        "regTime": "MORNING",
        "remark": "已满",
        "rest": false,
        "scheduleId": "482733:A",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周五"
      },
      {
        "leftNum": 0,
        "outCallType": "DEPT_COMMON",
        "price": "25.00",
        "regDate": "2023-08-04",
        "regTime": "AFTERNOON",
        "remark": "已满",
        "rest": false,
        "scheduleId": "482734:P",
        "testField": "1037800243:",
        "totalNum": 0,
        "weekDay": "周五"
      }
    ],
    "regScheduleVOList": [],
    "shortPinyin": "(NFMK)SZFYMZ",
    "sortOrder": 0,
    "type": "COMMON"
  },
  "errMsg": "获得普通排班情况成功!",
  "success": true
}

这是一个典型的把相关信息序列化成json然后回复在http body中的方式。而且这json回复的基本猜猜就懂是什么意思了。

3.2 刷票请求构造

既然这个后台也没做登陆机制,也没做cookies或者jwt会话管理验证机制,那么这里的刷票可就不繁琐的。正统的刷票过程一般一定要有登陆,拿到会话token,还需要实现token的刷新机制。但这里很厉害,啥都不要。也就是你会自动化构建http请求就行了。

构建http请求的方式可不要太多,人生苦短,我用python。来吧,上代码。

import time
import requests
import json
# import utils.sms as sms
import random


def eryuan():
    '''
    This function takes a URL as an argument and returns the corresponding
    eryuan number.
    '''
    url = 'https://mobiles.zhicall.cn/mobile-web/mobile/schedule/new/10361/dept/1037800243/info'  # 替换为实际的API URL

    headers = {
    'Host': 'mobiles.zhicall.cn',
    'Data-Sign': 'b475379efffb0ae96fd17b576d9edf53',
    'Accept': '*/*',
    'from': '0',
    'hospitalId': '10361',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': '91',
    'User-Agent': 'iPhone14,5(iOS/16.5.1) Uninview(Uninview/1.0.0) Weex/0.26.0 1125x2436',
    'Connection': 'keep-alive',
    }

    payload = 'fetchType=SCHEDULE_RESERVATION&expertType=SPECIALIST&hospitalId=10361&agencyId=10361&from=0'

    response = requests.post(url,headers=headers, json=payload)


    # 解析HTTP响应
    if response.status_code == 200:  # 检查响应状态码
        data = response.json()  # 解析JSON数据
        # 提取特定字段
        if 'data' in data and 'regNewScheduleVOList' in data['data']:
            res = data['data']['regNewScheduleVOList']
            print(res)
            for item  in res:
                if item['regTime'] == 'AFTERNOON':
                    if item['regDate'] == '2023-07-12' or item['regDate'] == '2023-07-13' or item['regDate'] == '2023-07-14':
                        resNum = int(item['leftNum'])  
                        if (resNum > resNum):
                            # sms.SMSIdentify.main(('13456789123', '抢到票嘞!' + item['regDate'] + str(resNum)))
                            print(item['regDate'] + ' yes!')
                        else:
                            # sms.SMSIdentify.main(('13456789123',str(resNum)))
                            print(item['regDate'] + ' No')
        else:
            print("未找到特定字段")    
        # 处理响应数据
        # print(data)
    else:
        print('请求失败:', response.status_code)

if __name__ == '__main__':
    while True:
        eryuan()
        time.sleep(random.uniform(3.0, 5.0))

由于博主有一个短信猫,所以这里仅仅写到刷到了有余票就自动给我自己发一条短信了。没有短信猫的,可以搞个自动发邮件给自己邮箱,大部分手机也有自动代收邮件的功能,基本也能做到1分钟以内的消息推送了。

4. 进一步折腾

如果能做到自动下单,岂不是更好。的确,我们继续分析一下他们的请求包里都有哪些东西。

POST https://mobiles.zhicall.cn/mobile-web/mobile/patient/get/familyMembers/true/_这里是5个大写A到F的字符,为了安全就不展示了/10356 HTTP/1.1

Host: mobiles.zhicall.cn
Data-Sign: ab421bfd4003f09c63a6cdb344b2192a
Accept: */*
from: 0
hospitalId: 10356
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh-Hans;q=0.9
token: 13456789123  
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
User-Agent: iPhone14,5(iOS/16.5.1) Uninview(Uninview/1.0.0) Weex/0.26.0 1125x2436
Connection: keep-alive

hospitalId=10356&agencyId=10356&from=0


这里请求体里东西很少,就只有一个医院的ID号,这个平台看来不止承接一家医院。主要的信息都在请求头里,唯一看起来有点麻烦的就是Data-Sign这个东西,里面看起来是一个没意义的字符串。这种大概率还是sha256或者md5值。这个值虽然在我们上面的登陆和查看余额请求中不填都可以,但因为我们没做抢票的自动化,所以也许Data-Sign 这个值在抢票的时候是需要的。

这个时候应该怎么办呢?

别忘了,我们的外包团队贴心的帮我们写好了Data-Sign相关的脚本,那个里面肯定有请求构造代码的。

// app-service.js部分代码截取
,s["hospitalId"]||d||(s["hospitalId"]=l.globalData.hospitalId);var m={"content-type":v[r]};return Object.assign(m,u),c&&(m["Data-Sign"]=encryptmd5(JSON.stringify(this.objToString(s)))),new Promise((function(i,n){uni.request({url:g,data:s,method:"POST",

这里截取部分代码,我们清晰的看到了,嗯,就是md5,这函数的名字写的是真的好。那么这个md5值是md5的什么东西呢?后面也告诉我们了,是把一个json串md5了一把。那么这里的json串到底是什么呢?我们注意下,最后uni.request,这个data就是s,然后encryptmd5这个函数也就是把body中的http url语法用json换了一下。

也就是对于上述请求中的 Data-Sign: ab421bfd4003f09c63a6cdb344b2192a 这个值,实际上是 hospitalId=10356&agencyId=10356&from=0的json表达。

验证一下猜想,构造json串

{"hospitalId":"10356","agencyId":"10356","from":"0"}

然后去md5网站随便搜一下

ab421bfd4003f09c63a6cdb344b2192a

好家伙,一模一样。所有请求的重要部分目前已经都弄通了,里面的cookies无非是服务器提供的会话缓存,后面请求的时候存一下就好,估计还是自动化下单需要缓存这些。

5. 总结

本文探究了某某某儿科医院APP的挂号请求全流程,探究了如何从猜想,到拆包APP,找到验证思路。通过抓包逐步了解问题,通过重放逐渐了解后台服务器运作逻辑,通过前端代码猜想请求内容填写的全过程。

本文遗留了自动化抢票部分的实现,但现有信息已经完全能做到自动化抢单,然后推送邮件告知手机要进行付款,即可完成自动抢票,碍于时间限制,目前暂未进行下去。

本文涉及工具推荐:

工具名工具作用适用平台
Stream手机APP抓包iOS
FindermacOS自带APP包解析macOS
RestClient便捷的vscode虚拟发http请求插件macOS,Windows,linux跨平台

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/821856.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Leecode】交替合并字符串- join

题目 给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。 返回 合并后的字符串 。 错误1 class Solution:def mergeAlternately(self, w…

微信小程序防盗链referer问题处理

公司使用百度云存储一些资源,然后现在要做防盗链,在CDN加入Referer白名单后发现PC是正常的,微信小程序无法正常访问资源了。然后是各种查啊,然后发现是微信小程序不支持Referer的修改,且在小程序开发工具是Referer是固…

想要对象吗?教你如何用C++new一个完美的对象(内存管理)

目录 一、C/C内存分布 1. 栈(Stack) 2. 堆(Heap) 3. 全局区/静态区(Global Area/Static Area) 4. 常量区(Constant Area) 5. 代码区(Code Area) 二、C…

智安网络|应对政务行业数字化转型中的数据隐私和网络攻击风险

政务数据共享安全咨询规划 每个政府部门面临的风险场景、合规要求都有所不同,因此首先需要通过数据安全咨询规划,完善数据安全制度规范,结合政务数据的实际业务需求,建立健全政务数据共享开放的全流程安全管理制度,明…

深度学习——注意力机制、自注意力机制

什么是注意力机制? 1.注意力机制的概念: 我们在听到一句话的时候,会不自觉的捕获关键信息,这种能力叫做注意力。 比如:“我吃了100个包子” 有的人会注意“我”,有的人会注意“100个”。 那么对于机器来说…

MySQL处理客户端请求

文章目录 一、连接管理二、解析与优化1、查询缓存2、语法解析3、查询优化 简单来说 MySQL 主要分为 Server 层和存储引擎层: Server 层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现&#xff0c…

【Shell】Shell编程之文本处理器——awk

sed可以对文本内容进行增删改查 主要使用的是改和查;查使用grep,正则表达式使用grep -E更好 awk是文本三剑客中最强大的文本工具; awk也是按行进行操作;对行操作完之后可以根据指定命令来取列 awk的分隔符:默认为 &…

Linux第七章之gdb与makefile使用

一、Linux调试器-gdb使用 1.1背景 程序的发布方式有两种,debug模式和release模式Linux gcc/g出来的二进制程序,默认是release模式要使用gdb调试,必须在源代码生成二进制程序的时候, 加上-g 选项[重要] 1.2开始使用 …

爬虫原理详解及requests抓包工具用法介绍

文章目录 一、什么是爬虫?二、爬虫的分类三、网址的构成四、爬虫的基本步骤五、动态页面和静态页面六、伪装请求头七、requests库介绍1. 概念:2. 安装方式(使用镜像源):3. 基本使用:4. response对象对应的方…

一起学算法(数组篇)

1.概念: 1.顺序存储 顺序存储结构,是指用一段地址连续的存储单元来依次存储结构,如图所示,每个蓝色方块都对应了数组中的一个数据,数据有类型,例如:32位整型int、单精度浮点型float、双精度浮点…

你知道HTTP与HTTPS有什么区别吗?

作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 目录 一、什么是HTTP? 二、什么是HTTPS? 三、HTTPS 的工作原理 1、客户端发起 HTTPS 请求 2、服务端的配置 3、…

如何设计一个Android端高性能日志监控系统

开发中客户端经常遇到一些线上问题, 无法复现, 但是又的的确确存在; 当线上反馈的时候无从下手; 主要是因为并不知道用户所处的环境,以及所做的操作顺序或者程序运行的顺序; 在排查问题和复现问题上占用了很大的成本; 如果debug时的log日志如果线上也能查看就好了; 基于此, 我们…

5.类型推论,类型断言,类型兼容性

目录 1 类型推论 2 类型断言 2.1 类型推论所带来的问题 2.2 基本使用 2.3 不断言会出现的问题 2.4 断言的另一种写法 2.5 查看DOM元素的类型 3 类型兼容性 3.1 类兼容性 3.2 接口兼容性 3.2.1 接口之间的兼容性 3.2.2 接口与类之间的兼容性 3.3 函数…

C++ 类的静态成员

在结构化程序设计中程序模块的基本单位是函数,因此模块间对内存中数据的共享是通过函数与和函数之间的数据共享来实现的,其中包括两个途径——参数传递和全局变量。 面向对象的程序设计方法兼顾数据的共享和保护,将数据与操作数据的函数封装…

解决运行flutter doctor --android-licenses时报错

问题描述: 配置flutter环境时,会使用flutter doctor命令来检查运行flutter的相关依赖是否配好。能看到还差 Android license status unknown.未解决。 C:\Users\ipkiss.wu>flutter doctor Flutter assets will be downloaded from https://storage.…

【MySQL】数据库的增删查改+备份与恢复

文章目录 一、创建数据库create二、数据库所使用的编码2.1 查询字符集和校验集2.2 指定编码创建数据库2.3 不同的校验集对比 三、删除数据库drop四、查看数据库show五、修改数据库alter六、数据库的备份与恢复6.1 备份 mysqldump6.2 恢复source6.3 仅备份几张表或备份多个数据库…

互联网宠物医院开发:宠物健康护航的新选择

随着人们对宠物的关注度逐渐提高,宠物医疗服务也得到了更多的关注和需求。而互联网宠物医院作为一种新兴的医疗服务形式,正以其独特的优势和便捷性受到越来越多宠物主人的青睐。   首先,互联网宠物医院的最大优势在于提供了便捷的服务。宠物…

寻找峰值——力扣162

文章目录 题目描述法一 寻找最大值法二 二分法 题目描述 法一 寻找最大值 int findPeakElement(vector<int>& nums){return max_element(nums.begin(), nums.end()) - nums.begin();}法二 二分法 int findPeakElement(vector<int>& nums) {int l 0, r n…

onnx模型的保存与使用

1 onnx模型的保存 在网络训练结束之后&#xff0c;通常会将模型的权重参数保存到.pth或.pt文件中&#xff0c;如果部署环境中有pytorch&#xff0c;那么直接新建一个模型类对象&#xff0c;然后导入权重参数即可&#xff0c;但如果部署环境中只有OpenCV&#xff0c;没有pytorc…

融合大数据、物联网和人工智能的智慧校园云平台源码 智慧学校源码

电子班牌系统用以展示各个班级的考勤信息、授课信息、精品课程、德育宣传、班级荣誉、校园电视台、考场信息、校园通知、班级风采&#xff0c;是智慧校园和智慧教室的对外呈现窗口&#xff0c;也是学校校园文化宣传和各种信息展示的重要载体。将大数据、物联网和人工智能等新兴…