搞定深圳新冠疫苗放号监控的那一夜

5.30 号晚上,到楼下散步的时候路过社康,发现一个通知:深圳从 6 月 1 日起,新冠疫苗全部改为线上预约才能打,顺便扫了下它贴的二维码,是【深圳卫健委】的公众号,点击进去之后发现号基本没了。用手机抓包看了下,简单分析了下发现页面的请求是可以被模拟的,于是回家开电脑研究了起来

阶段 1:抓包模拟

iOS 上有个特别好用的抓包软件,Stream,让手机抓包变得特别简单。

手机上走一遍请求疫苗信息,发现有多个请求,从多个请求中看 Response,确定 https://xgsz.szcdc.net/crmobile/outpatient/nearby 域名的 Post 请求就是我们的目标

虽然 Cookie 和 Post 字段中有类似 token 的字段,但我发现重放请求依然可以生效,这就意味着这个接口可以被脚本来模拟请求

阶段 2:curl 转 python

开电脑,把请求从 Stream 中导出为 curl 格式,在终端尝试用 curl 去请求,却发现一只返回的是乱码,一顿 Google 后依然没办法解决,于是赶紧转移战场。

第一时间想到的还是 Python,于是直接 Google “curl 转 Python”,得到 Python 代码,本地一运行果然可以

啊!顿悟人生哲理:聚焦目标,结果导向,不要钻牛角尖,有时候换个思路,问题直接迎刃而解

附转换工具:https://curl.trillworks.com/

阶段 3:分析关键字段

自此花了不到 5 分钟,我以为已经快要成功了,万万没想到分析关键字段这一步花了我大量的精力

我要的关键字段只有一个,就是这个社区有没有疫苗可以打,于是我天真的以为这是一个布尔值

其次,绝大多数的社康都是不可预约的状态,我无法找到一个可预约的状态来对比,以此确认是哪个字段

所以只能猜,我发现回包中有以下可疑字段:outpUse、outpWorkMode、outpLarge、status、vcinUse、nums、stock、orderNumber

把我心中的可疑字段都一一确认,竟然没有一个字段是符合我的设想。

比如 status,都是没有号的两个社区,一个是 true,一个是 false,那么它肯定不是我要的字段

有时候刷新会得到昙花一现的有号的社康,抓包后与无号的社康去对比,依然没有一个字段是符合我的设想

到这里我差点怀疑人生了

阶段 4:转移阵地

还好我机智的想到除了【深圳卫健委】还有另外一个可以预约的地方:【i 深圳】App,打开之后有一个重大发现

在【深圳卫健委】只有一个状态,状态真的混乱,【已约满】、【未放号】有啥区别,直接告诉用户能不能预约不就完事了!

而在这有两个状态:【有/无号】、【有/无疫苗】

到这我似乎豁然开朗了,一个社康要预约必须满足两个条件:有号+有疫苗,所以我要找的是两个字段的组合

重新把上面的字段按照先前的思路,进行差异化对比,终于让我发现了规律,status=1 表示有号,nums > 0 表示有疫苗,二者同时满足才是我要找的答案

下图是当时的推导过程

我自以为应该是一个布尔来表示一个状态,结果陷入思维定势。

啊!顿悟人生哲理:有时候,你的经验也是你的思维定势

阶段 5:完善脚本

搞定了字段就是完善脚本了,我只做给自己用,于是只关注南山和宝安两个地区,做个限制 1 分钟发一次,别太狠。

阶段 6:自动通知

好了,最后一步就是有号的时候如何通知到我呢?电脑上的脚本执行结果最好是能通知到手机,脑海里飘过 App、小程序、邮件推送,都觉得太重了。

灵感一现,想起之前好像看过一个推送的服务,方糖。到官网确认下眼神,就是我要找的人。

方糖推送,关注它的公众号,绑定自己的微信,就可以用脚本推送信息到公众号

神器。

最终效果:每隔一分钟,电脑就会自动查询疫苗接口,如果符合我的条件,我的微信就会收到提醒,点击进去就是有号的社康列表

最后的最后,脚本推送了很多次消息,我都没能抢到,反而不小心自己手动刷的时候抢到了号…

啊!顿悟人生哲理:运气比努力更重要

doge.jpg

本来这个脚本还有进一步优化的空间,由于我已经打了疫苗,故不再花时间于此

附:Github 地址

一杯冰可乐