某医院挂号记

近来有某医院的产科挂号需求,平台规则:

  • 放号时间:每天8:00 AM
  • 挂号时间:8:00-23:00
  • 男性不能挂产科
  • 产科必须使用人脸识别验证通过后,自动提交挂号(人脸数据有效期1分钟以内,每次验证人脸需要13-15秒左右)
  • 只能通过微信网页端操作挂号
  • [更新]每10s只能提交1次验证

关注退号情况

每30s检查一次,有余号则推送到Bark,以下为python实现

 1 import requests
 2 import time
 3 s = requests.session()
 4 ###带连续*号为地址隐藏
 5 def send_err(text):
 6     url = f'https://api.day.app/******/挂号错误提醒/{text}?sound=update&isArchive=1&level=timeSensitive'
 7     requests.get(url)
 8 def send_hook(text):
 9     url = f'https://api.day.app/******/挂号提醒/{text}?isArchive=1&sound=update&level=timeSensitive&url=wechat://'
10     requests.get(url)
11     url = f'https://api.day.app/******/挂号提醒/{text}?isArchive=1&sound=update&level=timeSensitive&url=wechat://'
12     requests.get(url)
13 def get_phpsessid(times = 3):
14     #获取云中的phpsessid
15     try:
16         return requests.get('https://******?id=7ri5os2y&projectid=21020216034545855318',timeout = 2).json()['data']['SYS_string1']
17     except:
18         print(f'phpsessid获取失败,{times}s后重试')
19         send_err('phosessid获取失败')
20         time.sleep(times)
21         times += 1
22         return get_phpsessid(times)
23 def get_doc_list(deptId):
24     phpsessid = get_phpsessid()
25     s.headers.update({
26         'User-Agent':'Mozilla/5.0 (iPhone; CPU iPhone OS 15_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.29(0x18001d38) NetType/4G Language/zh_CN',
27         'cookie':f'PHPSESSID='+phpsessid,
28         'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
29         })
30     #获取排班列表
31     url = 'https://******/index.php?g=WapApi&m=Register&a=getRegistDate'
32     date_c = 'g=WapApi&m=Register&a=getRegistDate'
33     try:
34         r = s.post(url,data=date_c,timeout=2).json()
35     except:
36         print(f'获取排班日期失败,5s后重试')
37         time.sleep(5)
38         return get_doc_list(deptId)
39     date_list = [i['date'] for i in r['data'][::-1] if i['stop']==0]#排除掉stop=1的日期项,周末没有建档号
40 
41     #获取医生列表
42     for day in date_list:
43         url = 'https://******/index.php?g=WapApi&m=Register&a=getDoctorList'
44         c = f'deptId={deptId}&date={day}&SessionType=&LabelId=0&districtCode=2'
45         r = s.post(url=url,data=c).json()
46         if r['state'] == 1:
47             for doc in r['data']:
48                 if f"{doc['SeqNoStrLast']}" != '0':
49                     docName = doc['docName']#医生姓名
50                     period = doc['period']#上下午
51                     number = doc['SeqNoStrLast']#余号
52                     text = f'{day} {period}-{docName}-余{number}'
53                     # print(text)
54                     send_hook(text)
55         else:
56             text = r['errorMsg']
57             send_err(f'挂号系统报错{text},10s后重试')
58             time.sleep(10)
59             return get_doc_list(deptId)
60         time.sleep(1)
61 
62 ############参数 start#############
63 #deptId:产科-1336,产后复查-1933
64 deptId = 1336
65 ############参数 end#############
66 while 1:
67     get_doc_list(deptId)
68     print('.',end='')
69     time.sleep(30)

准备工作:

为方便分析网络请求,可在web端登录此网站,使用Edge浏览器+修改请求头的插件(Gooreplacer)

在插件中设置请求头修改参数,只需修改User-Agent、Cookie两个参数。若设置正确,则可正常进入web端

经测试,web端不能挂号成功(挂号成功后没有付款信息,在挂号列表也不会有显示)

【妇产科>产科】的号比较紧缺,不好测试业务逻辑(主要是人脸);可以选择【妇产科>产后复查门诊】等,号源比较充足且能验证人脸的类目测试

 


方案1:绕过人脸识别(失败)

通过抓包,在确认挂号阶段,有一个html文件"**/tpl/Wap/default/WxView/registerAndAppoint/selectCard.html"

(经验证,此文件与登录者无关,代码完全一致)

描述人脸或图片验证的选择方式:

红框部分的意思为:请求http://***isFace,若返回的**asdfafs为“binoigaibno”,则启用人脸,否则弹出验证码,验证:

通过抓包得到isFace的返回数据可见,只需修改返回的binoigaibno则可直接启用验证码可以直接Mock此请求

下面是测试,可以Mock成功,原本应该验证人脸的已经改成图片,但是在提交阶段验证失败,无解。

同理,修改Html文件,使其100%走人脸,仍然出现上述情况


 方案2:卡点提交(重放请求)

根据挂号流程:在7:45会开启人脸识别通道(按键变绿),通过后,自动提交挂号申请。但每次人脸识别的时间不一致,提交挂号的时间点不可控制。

首先想到是把人脸请求包在本地截断,等到8:00再手动放出去(可以用机器重放,时间更精准)

再进一步人脸识别时间兴许可以提前,可以在倒计时上下点功夫

再再进一步,可以多终端登录,提升成功率(2023.02.27更新:策略更新,不支持连续提交)

需要注意,经测试,人脸识别成功的数据包有效期只有45s左右,加之每次识别需要15s左右的时间,所以只能准备2-4个请求包。

· 改善点:Moke时间请求

通过网络分析可以发现每进入挂号页面会有一次检查时间的请求,URL包含"checkTime",可以将此请求Mock,使倒计时提前结束,提前进入挂号流程:

Ps:在Edge浏览器中可以使用requestly插件实现Mock

· 改善点:取消人脸等待时间

经测试,每次验证成功后到提交挂号数据有一定延迟,检查Html代码可以定位到,可以将此处置为1

· 改善点:手动提交挂号

经测试,每次挂号后均是自动提交挂号,这里可以借助weui.dialog提醒模块,将流程改为弹出窗口提醒

将提交方法塞进确定按钮里,即可实现点确认再提交挂号

· 改善点:机器提交

将多个挂号请求包保存到本地,机器设置定时发送,或许可以增加成功率

· 改善点:矫正时间

由于本地时间可能与服务器时间有误差,故取服务器时间,到点后自动提交

posted @ 2023-01-10 14:31  airgeek  阅读(98)  评论(12编辑  收藏  举报