news 2026/9/24 15:16:50

大麦抢票自动化:从详情页到提交订单,把整个流程压进10秒

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大麦抢票自动化:从详情页到提交订单,把整个流程压进10秒

大麦抢票自动化:从详情页到提交订单,把整个流程压进10秒

【免费下载链接】ticket-purchase大麦自动抢票,支持人员、城市、日期场次、价格选择项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase

你有没有过这种体验:演出开票时间一到,鼠标停在按钮上,等它变成可点击的那一瞬间,屏幕已经跳成了"已售罄"。开源大麦自动抢票脚本 ticket-purchase 干的就是这件事——Web 端用 Selenium 驱动 Chrome,移动端用 Appium 驱动安卓手机上的大麦 APP,把"选城市 → 选场次 → 选票价 → 勾观演人 → 提交订单"整条链路自动跑完。你只负责三件事:改配置、扫码登录、按回车。

最小可运行路径:5分钟把大麦抢票跑起来

Web 端依赖最少,建议先跑通它摸熟流程。一共 8 步,移动端的部分单独标注:

  1. 获取代码并安装 Python 依赖(要求 Python 3.9+),一条命令完成:
git clone https://gitcode.com/GitHub_Trending/ti/ticket-purchase cd ticket-purchase pip install -r damai/requirements.txt
  1. 新建damai/config.json。脚本启动时会校验字段,缺了会直接把模板打印到控制台,模板见下文配置速查一节。
  2. 运行 Web 端主程序。第一次会弹出浏览器让你扫码,Cookie 会存成damai/damai_cookies.pkl,之后每次运行自动加载,不用再扫:
cd damai python damai.py

✅ Web 端到此结束。接下来 5 步是移动端,热门演出的票经常只有 APP 能买,这条路迟早要铺:

  1. 安装 Appium 及 UiAutomator2 驱动(Node 需 20.19+ / 22.12+ / 24+,版本太低起不来)。
  2. 启动 Appium 服务并确认adb devices里能看到设备,手机装好大麦 APP 并登录账号。
  3. 在手机上打开大麦,手动搜索并进入目标演出的详情页(脚本从详情页接管,不需要它自己搜索)。
  4. 编辑damai_appium/config.jsonc,填keyworduserscitydate,重点确认price_index
  5. 跑抢票脚本,前面几步连起来就是:
npm install -g appium && appium driver install uiautomator2 appium --port 4723 cd damai_appium && python damai_app_v2.py

target_url从哪来?打开大麦 PC 端的演出详情页,把地址栏整条复制过去即可。配置里每个字段对应页面上哪个位置,看这张标注图:

内部机制:一个状态机在驱动大麦抢票

Web 端的核心思路是"预置 + 轮询"。登录完成后,脚本先在详情页把城市、场次、票价、数量全部选好(预置),然后进入轮询循环:每隔 0.2~0.3 秒读一次购买按钮的文本,看到"立即购买"或"立即预订"就立刻点,再靠页面标题和 URL 判断是否跳进了订单确认页。如果按钮还显示"提交缺货登记",说明没开票,自动刷新继续等。可以把它理解成一个每几秒查一次门的保安,门一开就冲进去。

进到订单确认页后,选观演人是最容易出错的环节——不同版本的页面 DOM 结构会变,所以脚本对"勾人"准备了 4 套定位方案依次尝试:按用户名文本找 div → 用 label 关联复选框 → 直接点包含用户名的元素 → 走 JS 脚本精确定位,哪套先成功走哪套。提交订单同理,有 5 套兜底。移动端流程更直白:城市 → 预约按钮 → 票价 → 数量 → 确定购买 → 勾选观演人 → 提交订单,任何一步失败就断开重连驱动,最多重试 3 轮。

各阶段的分工可以这样看:

阶段干什么关键机制
预置详情页选城市/场次/票价/数量配置支持多格式模糊匹配,如"2023-10-28"和"10月28日"
轮询盯住购买按钮快速模式每 0.3 秒一次;"缺货登记"则刷新重等
订单确认勾观演人、提交4 套/5 套定位方案轮询兜底,任一成功即通过
重试断连、元素没找到移动端自动重建驱动,3 轮内恢复

关键配置速查:这些配置项决定速度上限

两端配置都在 JSON 里,参数不多但每个都影响结果:

参数作用推荐值/示例
target_url(Web)演出详情页地址,脚本只认它从浏览器地址栏复制
users(双端)观演人名单,人数即票数["姓名1", "姓名2"]
dates/prices(Web)场次与票价匹配条件多格式并存,如["1039", "¥1039"]
city/date/price(App)城市、日期、票价描述price_index必须手动数对
fast_mode(Web)开关等待/日志策略true
max_retries(Web)轮询刷新的最大次数1000 起步,预售日可加大
if_listen(Web)遇到"缺货登记"是否继续监听(盯回流票)true
if_commit_order(双端)是否自动提交订单调试期设false,验证通过再改true

下面是一份 Web 端完整配置,照抄改值即可用:

{ "index_url": "https://www.damai.cn/", "login_url": "https://passport.damai.cn/login", "target_url": "https://detail.damai.cn/item.htm?id=演出ID", "users": ["姓名1", "姓名2"], "city": "广州", "dates": ["2023-10-28", "10月28日"], "prices": ["1039", "¥1039", "1039元"], "if_listen": true, "if_commit_order": false, "max_retries": 3000, "fast_mode": true }

仓库里的移动端配置damai_appium/config.jsonc已经是一份可直接参考的真实示例,结构更简单,8 个字段全在上面表格里。编辑器里实际长这样:

进阶技巧:把抢票压到毫秒级的三个手法

点击提速:坐标点击替代元素点击

你遇到的问题:Appium 默认的element.click()单次常常 100ms 以上,勾两个观演人就耗掉好几百毫秒。

背后的原因:常规 click 要走可访问性层,而且 UiAutomator2 默认会等页面"空闲"才执行动作。

具体做法:v2 版本全部改用mobile: clickGesture发坐标直点,duration只有 50ms;同时把waitForIdleTimeout设为 0,不再等页面空闲。设备侧再顺手关掉三组动画开关,界面切换无残帧:

adb shell settings put global window_animation_scale 0 adb shell settings put global transition_animation_scale 0 adb shell settings put global animator_duration_scale 0

实测效果:单次点击从约 100ms+ 压到 50ms;多人勾选时脚本先批量收集全部坐标再连续点,间隔仅 10ms,选 2 个人几乎是瞬时的。

票价文本是空串:改用位置索引定位

你遇到的问题:APP 更新后,按文本找票价按钮的 XPath 全部失效。

背后的原因:新版界面把票价行重做了,按钮文本变成动态绘制,视图树里拿到的是空字符串"",按文字定位从根上不成立。

具体做法:v2 改按"第几个可点击控件"定位——在票价容器里找index = price_index的 FrameLayout 直接点。所以price_index必须手动数(从 0 开始),仓库示例里周深深圳站的"内场1199元"就是 5。

实测效果:票价选择从必挂变成稳定命中;代价是换一场演出要重新数一次索引,对单场抢票完全可接受。

打开 fast_mode:轮询间隔从 1 秒降到 0.3 秒

你遇到的问题:正常模式下轮询刷新要等 1 秒,开票这种"秒售罄"的场景里这是致命差距。

背后的原因:正常模式给每个环节都留了调试余量——固定 sleep、大量页面扫描日志。

具体做法fast_mode设为true后,点击后等待 0.5s → 0.1s,轮询间隔 1s → 0.3s,订单页加载从固定 sleep 换成显式等待,调试扫描日志整体跳过。

实测效果:预置阶段总耗时减半以上;配合 Cookie 登录免扫码,脚本从启动到走到"已提交订单"能控制在几秒内。

高频踩坑:这四个问题一行命令解决

Appium 启动时报 Node 版本不兼容。根因:Node 太旧,Appium 3.x 只认 20.19+ / 22.12+ / 24+。 解法:brew upgrade node(Linux 用 nvm 装 22 再切换)。

脚本报 "Neither ANDROID_HOME nor ANDROID_SDK_ROOT environment variable was exported"。根因:找不到 adb,SDK 环境变量没配。 解法:把ANDROID_HOMEANDROID_SDK_ROOT都指向 SDK 安装目录(macOS 默认~/Library/Android/sdk),并写进 shell 配置文件。

adb devices 里看不到设备,报 Unable to find an active device。根因:手机没开 USB 调试,或模拟器压根没启动。 解法:真机重插重认一次,模拟器用emulator -avd 你的设备名启动后再跑adb devices确认。

仓库里的一键脚本start_appium.sh/start_ticket_grabbing.sh直接跑报错。根因:脚本里的 ANDROID_HOME 和 python 路径是作者 Mac 的硬编码路径。 解法:改脚本开头的两行export,或干脆按本文最小路径里的裸命令手动执行。

另外两个小提醒:Web 端如果 Chrome 升级后驱动版本报错,跑一次python damai/check_environment.py会自动检测并安装匹配的 ChromeDriver;Web 端 Cookie 过期(总被弹回登录页)时,删掉damai/damai_cookies.pkl重跑一次重新扫码即可。

使用边界:几句温和的提醒

  • 建议用专门的小号跑脚本,配置文件是明文 JSON,别把真实敏感信息提交进仓库。
  • 轮询间隔是为"没开票"设计的等待,不是让你把请求频率拉满去压接口,保持脚本默认节奏即可。
  • 平台对高频自动化有风控手段,抢到与否看运气,别把期望建立在"必中"上,更别用于倒卖——项目方也明确声明仅供学习研究、不用于商业用途。
  • 实名购票意味着票最终只属于你本人,抢到的票好好看演出。

继续深挖:跑通之后值得看的 4 个路径

  • damai_appium/app.md:移动端 V2 版的设计笔记,讲清楚为什么引入price_index、为什么换clickGesture,理解"作者为什么这么优化"最快的材料。
  • damai/check_environment.py:Web 端 ChromeDriver 的自动检测与安装逻辑,想给自己的项目写环境自检可以抄思路。
  • 完整使用指南(PC端).md.md):PC 端从登录到订单页的完整操作手册,卡在某一步时按图排查。
  • tests/:单元测试骨架,看它怎么校验配置合法性,能帮你理解脚本对输入的预期。

下次开票时间到,你不需要盯着鼠标等它变绿,只需要看控制台滚到"订单已提交",再瞄一眼那句"耗时 X.XX 秒"——19:00 那场和"已售罄"的故事,到此可以翻篇了。

【免费下载链接】ticket-purchase大麦自动抢票,支持人员、城市、日期场次、价格选择项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!