当我得知我喜欢的乐队 MyGO!!!!!将于上海开演唱会时,我内心十分激动。然而,票务代理却是臭名昭著的 EUPD,他们以放票少,官牛多而出名,让无数抢不到票的粉丝伤透了心。
当抢票信息公布后,我并不打算直接用手机去抢票,因为这样成功率实在是太低了,感觉就跟原神无保底单抽出金的概率差不多吧。
作为一个还算懂点技术的人,我决定利用我平时所学,打造出几个抢票利器,来助我一臂之力。
自动化连点器
抢票开始时,我们一般都会拼了命地去点击抢票界面上的按钮。
但是呢,人点击按钮,是会有时间差的,你无法保证在开票时正正好好地点到按钮,总是会有个几十毫秒的误差,连点亦是如此,你 1 秒钟连点按钮的次数一般最多不会超过 10 次。尽管这对于一般的演唱会来说不算什么,但对于那种特别火热的演唱会,错过几毫秒,错过几次连点可能也会让你痛失机会。
是不是感觉自己太弱小了?
DIO 曾说过:人是有极限的,正因如此才要超越人类!
那我们如何在现实中获得这般“超越人类”的力量呢?答案是程序。
我们人做动作基本都是以秒为单位来计算的,然而,对于程序的运行速度来说,基本都是以毫秒为单位计算的,秒和毫秒可是相差了足足 1000 倍。
知道了这一点,那我们就可以让程序来帮我们连点,不仅能在操作速度上有巨大的提高,而且程序自带的定时器可比我们自己估算的时间要准的多,基本可以消灭开抢时时间上的误差。
接下来,我们将使用AutoX.js这个强大的程序来实现我们的抢票大业,注意这个程序目前来说只有安卓版的,并没有其他环境(如 ios)的版本。
安卓环境
首先,你需要一个安卓手机,用来提供程序运行所需要的环境。
有的人会说:emmmm 我是苹果机啊,总不见得为了抢票特地去买个安卓机吧?
没有安卓机怎么办?也行!我们可以下一个安卓模拟器,在电脑上就可以运行。模拟器的话个人推荐用网易的mumu 模拟器。
安装程序
AutoX.js
的 apk 可以在 Github 的Releases 页下载到。
对于手机而言,可以把 apk 先打包成压缩包,然后通过一些平台(如微信)进行传输,再下个解压缩的软件,解压缩后即可进行安装。
模拟器就简单了,直接把 apk 拖上去,就可以安装。
准备工作
安装完成后,我们直接进入 AutoX.js 这个软件。
打开无障碍服务
点击左上角的三道杠。
找到“无障碍服务”,将它后面的开关打开,它会弹出一个提示,按提示去设置里打开应用的无障碍选项就行了。
显示指针位置
我们写程序时,有时需要知道我们目前的手指点在手机的哪个位置。
找到“系统应用-设置-关于手机”,最底下有个版本号,连点几下,直到它提示你进入了开发者模式,就 OK 了。
然后,我们回到“设置-系统”,里面会有一个“开发者选项”,进去,找到“指针位置”,打开它。(上面有个“显示点按操作反馈”建议也打开下)
你会发现画面上方多了一些数据,其中 dX 和 dY 就是指针位置的数据了,当我们点击手机或模拟器上的一个位置时,它们的值会跟着改变。
拾取控件信息
当我们浏览和操作 app 时,会接触 app 的很多元素(如点击按钮等),这些都是 app 的控件。
想在脚本里操作 app 的控件的话,往往需要知道控件所包含的信息才能选中并操作它,最直观的是它所包含的文字。
除了文字外,我们还可以通过工具来拾取它的控件名称等信息。
回到 AutoX.js 软件,点击左上角的三道杠。
找到“悬浮窗”,将它后面的开关打开。(如果有询问权限的话直接打开权限开关)
这样我们就能在画面左侧发现一个悬浮菜单,点击菜单,它会自动展开,再点击它的第三个按钮。
会出现一个弹窗,选择“布局范围分析”。
然后它会把整个页面的结构都显示得清清楚楚。
点击最下面的“缺货登记”按钮,再点击“查看控件信息”,我们就能看到这个按钮的所有控件信息了。
AutoX.js 甚至还贴心地准备了一个自动生成代码的功能,再次点击按钮,选择“自动生成代码”,它就能直接生成供脚本使用的代码,而且各种场合都考虑到了。
我们试试生成这个脚本:找到“缺货登记”按钮并点击它。
生成的代码如下:
1 | className("android.widget.TextView").text("缺货登记").findOne().click(); |
连接电脑
我们先在自己的编辑器里安装一个扩展,以 vscode 为例,扩展名叫“Auto.js-Autox.js-VSCodeExt”,安装好后是这样的:
按下“Ctrl+Shift+P”快捷键,搜索 autoxjs,找到“开启服务”这个命令并点击它:
画面右下角会显示连接的服务器地址:
回到 AutoX.js 软件,点击左上角的三道杠。
找到“连接电脑”,将它后面的开关打开。
它会提示你输入服务器地址,就输入刚刚右下角弹出来的服务器地址,再加一个ws://
的前缀,因为服务器用的是WebSocket
来连接的,输完后点击“确定”按钮,即可完成连接。
注意:我用的是模拟器,可以直接连接,如果用真机的话,可能会有风控应用禁止连接,目前还没想到用什么办法来解决。
写脚本代码
所有的准备工作完成后,我们总算可以着手开始写代码了。
写代码前,建议先通读下 AutoX.js 的官方文档,了解它常用的 API 函数。
我们先大致理一下脚本所要做的逻辑:抢票开始前一直等待,当购票按钮出现时立刻点击它进入选票页面,然后在选票页面拼命地点“确认”按钮,直到“立即支付”按钮出现后,我们就算进入了最后一个关卡——确认支付页,这里就不停地点“立即支付”按钮就可以了。如果抢票人数过多,就可能会跳出“前方拥堵”的提示,我们再创建一个子线程,用来专门点掉这个提示的“刷新”按钮。
我写的脚本一定程度上参考了这个:https://github.com/Pactum7/ticket-grabbing/blob/main/MaoYan/MaoYanGoNew.js
1 | // 检查无障碍服务是否已经启用,如果没有启用则跳转到无障碍服务启用界面,并等待无障碍服务启动;当无障碍服务启动后脚本会继续运行。 |
写好脚本后,我们就可以点击右上角的运行按钮,来运行这个脚本了。
注意:在运行脚本前,你需要提前登录好,并且填完所有预约信息,再进入演出页面启动,才能让脚本正常地运行。
还有一点:像猫眼这类 app,是会不停地更新换代的,可能过了一段时间后,app 的 UI 界面会发生一定的变化,那么你之前写好的脚本就可能会失灵!这时你就要重新开始拾取新界面上的控件数据,调整点击的坐标,修改你的脚本代码了。
改包提前进抢票页
在抢票开始之前,界面是长这个样的:
你点击下方的“已预约”按钮,只会进入预选择票档页,而不会进入正式的选票页,因为开票时间还没到嘛。
那么有没有一种办法,来“欺骗” app 以为已经到了开票时间,而显示出购票按钮呢?答案是有的。
我用的是 iphone,就以 ios 系统为例吧。
进入 App Store,搜索“Storm Sniffer”,安装这个 app,它的图标是一只“小螃蟹”,下文也这么称呼它。
它的完整功能需要付费 18 元,我是觉得为了抢票这点小钱也无所谓了,当然如果你不愿意付费的话,可以直接跳过这一部分~
解锁小螃蟹后,我们会重点使用它的“抓包”和“重写”功能。
我们先要开启 MITM,用来解密 app 的 HTTPS 流量,这个只要根据它的说明一步步做就行,开启后,我们就可以开始抓包了。
抓包
小螃蟹里打开抓包开关,再点“启动”按钮。
我们在 app 上找一个已经开票的演唱会,进入页面,等页面加载完毕后,再回到小螃蟹,点击“停止”按钮。
点击抓包的“历史记录”,我们就能看到抓到的所有的包了。
找到演出详情的包,它的链接里包含“/my/odea/project/detail”,查看它的响应数据。
然后进一个还没开票的演唱会,重复上面的步骤。
将两者对比下,我们就能发现跟按钮显示相关的 2 个数据不一样:saleStatus
和ticketStatus
,未开票时,两者的值都是 1,开票后,两者的值变成了 3。
重写
我们的目的,就是要把未开票的界面变成已开票的界面。
从上面可以得知,为了做到这一点,我们可以把包里的数据进行“重写”,比如saleStatus
原本是 1 的,将它改写为 3,不就行了吗。
回到小螃蟹,点击“重写规则”,再点击右上角的加号,即可添加新的规则。
以上则是我个人的规则,主要就是对特定链接的响应进行文本替换。
添加完成后,我们返回规则列表,勾选好我们新增的规则,再返回主界面,打开重写开关,启动小螃蟹。
回到上次未开票的那个演出,我们就会惊讶地发现它的按钮真的变成了已开票时的按钮“立即购票”!
不过呢,先别高兴的太早。我们点击购票按钮后,尽管会跳转到购票界面,但它会显示出这个结果:
啊嘞?不是已经骗过了 app 吗?怎么它还会提示这个?
nonono,其实进入购票页面时,app 还是会请求购票的数据,刚刚我们修改的仅仅是演出的数据,跟它是两码事,由于演出实际上未开始,购票的数据肯定也会返回未开票时的数据,到这里重写就暂时无能为力了。
话虽如此,但我们已经可以比其他人提前进购票页面了不是吗?
只要抓准时机,在开票前的 1 秒内提前点“立即购票”按钮,我们就能提前几百毫秒进入购票页。可别小看这点时间,在抢票面前,时间就是金钱!
那么如何把握住时间呢?我们需要一个精确到 0.1 秒的悬浮时钟,App Store 上搜索“ZK 助手”并安装它。
打开“ZK 助手”,点击“开启画中画”按钮。
如果你是 iPhone14Pro 以上的机型,也可以打开“显示到灵动岛”这个开关。
返回 app,你就能看到悬浮时钟已经出现在某个角落了,同时小螃蟹开着的话,下方的按钮也是“立即购票”。
当抢票即将开始前,你就可以等时钟走到最后 1 秒的某一刻,点击“立即购票”按钮,比别人抢先进入购票页了。
注意万万不能提前点,否则会出现“演出信息发生变化”的提示,返回会拖延几秒时间,直接导致你的抢票 GG。
但就算提前进了,也不排除有人也会用这招,因此不能松懈,战斗才刚刚开始!
监控回流票
当你完成抢票这场激烈的战斗后,你可能赢了,也可能输了。
技术,只能大大提高你成功的概率,然而,并不能确保你百分百能抢到你想要的票。
倘若票秒空了,你依旧没能抢到票,不要放弃,因为可能还会有回流票。
也不排除回流票很快就被其他人抢掉的情况,这时就得看你的运气了。
运气好,你就能蹲到并抢到回流票;运气不好,你和回流票会不停地失之交臂。
不论结果如何,你得知道啥时候有回流票。
我在网上找了个 python 写的回流票监控脚本,地址:https://github.com/ThinkerWen/TicketMonitoring
用起来也很简单,你只需在 config.json 中配置好演出的 id(可通过 app 抓包获得)、名称、平台(猫眼是 1)以及监控截止时间,就能直接运行脚本进行监控了。
如果你想在有票的时候收到手机上的通知,你需要再装一个发通知的 app,App Store 上搜索 Bark 并安装它。
打开 Bark app 后,将链接https://api.day.app/
后面的一串代码复制到电脑上,替换掉 Monitor.py 的”BARK_PUSH_KEY”,再开启脚本,就能在检测到回流票的时候给手机发通知了。
保持脚本与接口同步
实在不巧,我找的回流脚本其实已经失灵了,因为猫眼已经更新了演出的相关接口,当我得知这一点后顿时感觉之前都白监控了。
既然如此,就只好把脚本也更新一下了,让它和新接口相同步。
确保所有设备时间同步
有一个很容易被忽视的一个点:所有抢票设备的时间是否和当前的时间同步?
如果同步,OK 没什么问题。
如果不同步,我们要手动同步一下最新的时间。
同步电脑时间
以 win10 系统为例,打开“设置-时间与语言”,点击“同步时钟”,即可完成同步。
然后再重启下模拟器,看下抢票底部的倒计时是否跟手机一致,一致的话就表明同步成功了。
同步手机时间
手机上,我们通过 ZK 助手来看时间的,但这个 app 的时间往往会跟实际的时间有一定的误差,只要对比下电脑就可以得知。
我们可以把时间源锁定在“北京时间”。
我个人的抢票经历
如你所见,我用了上文写到的所有技术,来抢 MyGO!!!!!的这次 live。
第一轮,我很有自信,直接瞄准 1380 档,结果令我万万没想到的是这一档竟然是最先被抢完的,而且 1 秒钟都不到,我的脚本和小螃蟹全都被卡在了支付页,提示“库存不足”。
第二轮,我决定退一步,选择少难(?)一点的 1180 档,为了确保抢到甚至还找了个代抢,结果还是梅开二度,我和代抢双双阵亡……
第三轮,就放几张票,有抢到的可能吗?别想了。
至于回流票?说实话我都没意识到当时用的是过时的监控脚本,直到两轮都抢完后才发现,唉。
花了这么大的功夫抢票,最终依旧是一场空。错的不是我,是扣弄塞该哒!
最后
祝愿大家都能抢到自己想抢的票,就算没抢到,也绝不要向黄牛屈服!