ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

把点击“立即购买“改写成 3 次 HTTP 请求:大麦抢票脚本 Automatic_ticket_purchase 技术拆解

把点击“立即购买“改写成 3 次 HTTP 请求:大麦抢票脚本 Automatic_ticket_purchase 技术拆解

把点击"立即购买"改写成 3 次 HTTP 请求:大麦抢票脚本 Automatic_ticket_purchase 技术拆解

【免费下载链接】Automatic_ticket_purchase大麦网抢票脚本项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase

Automatic_ticket_purchase 是大麦网自动化抢票脚本,核心思路是逆向页面背后的接口,配合 Cookie 复用与 MD5 签名计算,把抢票流程改写为 3 次 HTTP 请求。适合想研究接口逆向、状态轮询和自动化下单的技术读者。

一、手工抢票卡在哪三步

开票瞬间,人手抢票的链条是:页面加载完、按钮渲染出可点状态、看清票档、点下购买、填完观演人。每一步都依赖浏览器渲染,而热门场次从开票到售罄通常以秒计,页面往往还没渲染完,按钮已经变成灰色。

具体痛点有 3 个:

  • 渲染耗时不可控:页面资源、脚本执行、按钮状态更新串行发生,人工操作快不过渲染管线;
  • 参数全靠手填:item_id、观演人、票档、数量都是表单里的隐藏字段,填错一个就前功尽弃;
  • 会话反复失效:Cookie 过期后,每次运行都要重新扫码或输密码,白白消耗抢票前的准备时间。

二、整体链路:浏览器只干一件事

先给全局视图。整个流程是四步串联,浏览器只出现在第一步:

  1. Selenium 打开登录页完成登录,取出全部 Cookie 写入本地cookies.pkl;
  2. 之后全程不再打开页面,用 requests 轮询detail.damai.cn/subpage接口读按钮状态;
  3. 状态变为"立即购买"后,请求buy.damai.cn/orderConfirm组装订单参数;
  4. 从返回数据里匹配观演人,POSTcreateOrder完成下单。

大麦常用观影人管理界面,下单参数自动从返回数据中匹配,免去手动选择

主循环入口在 run(),登录、Cookie、参数获取全部收敛在 tools.py 里,两个文件职责分得很清。

三、核心机制拆解

🎯 登录之后,页面直接下线

怎么运作:Cookie 是登录态的凭证,拿到它就等于浏览器会话,之后所有请求带上 Cookie 即可冒充"已登录用户"。

怎么落地:account_login() 用 Selenium 完成登录后,把所有 Cookie 转成字典返回;save_cookies() 将其 pickle 到cookies.pkl。下次运行,run()先探测该文件,存在就直接load_cookies(),全程零浏览器:

if os.path.exists('cookies.pkl'): cookies = tools.load_cookies() # 复用上次会话,跳过登录 self.login_cookies.update(cookies) elif 'account' == args.mode.lower(): self.login_cookies = tools.account_login('account', self.login_id, self.login_password) else: self.login_cookies = tools.account_login('qr') # 扫码登录

结果如何:登录从"每次必做"变成"一次 + 偶发刷新"。check_login_status()通过请求个人信息页并比对标题是否为"我的大麦-个人信息"来判定会话是否仍有效,失败时提示删除 Cookie 文件重登,失败路径也是明确的。

🕹️ 关键参数不手填,从官方 JS 里正则抠出来

怎么运作:调用subpage接口需要两组参数——商品参数commodity_param和下单扩展参数exParams。它们硬编码在前端构建产物里,手动抄写既易错又难跟随版本更新。

怎么落地:get_api_param() 每次运行时直接请求 CDN 上当前版本的vendor.js,perform.js,再用正则从混淆产物中把两段参数对象抽出来解析成字典:

js_code_define = requests.get( "https://g.alicdn.com/damai/??/vue-pc/0.0.70/vendor.js,vue-pc/0.0.70/perform/perform.js").text commodity_param = re.search('getSkuData:function.*?\|\|""}}', js_code_define).group() commodity_param = re.search('data:{.*?\|\|""}}', commodity_param).group()

结果如何:参数随官方 JS 自动更新,不用人工同步。代价同样直接——源码注释写明,大麦前端代码结构一旦变化,函数里的正则就得跟着改。这是整套方案里最脆的一环。

🧮 选座链路:MD5 签名本地重算

怎么运作:选座购买要走mtop.damai.cn网关,每个请求都要求携带sign字段——服务端用它校验请求未被篡改。sign的输入是 Cookie 中的h5_token、毫秒级时间戳和拼接后的业务参数。

怎么落地:签名算法是标准 MD5,被混淆在网页 JS 里。仓库把它抽成 signcode.js(calcaulate函数),由 get_sign_code() 借 Node 执行环境execjs在本地重算:

node = execjs.get() with open('signcode.js', 'r', encoding='utf-8') as f: js_file = f.read() js_exec = node.compile(js_file) param1 = '{}&{}&12574478&'.format(h5_token, time_stamp) # token+时间戳+appKey sign_code = js_exec.call('calcaulate', param1 + api_param)

结果如何:三个选座接口(dynamicinfo、getB2B2CAreaInfo、queryseatstatus)都能带合法签名访问,进而拉取座位 JSON、过滤noseat不可售座位、按票档挑出buy_nums个seatId。V2.1 由此支持了指定价位的选座购买,代价是只支持单价位、暂不支持连坐。

四、常规做法 vs 本方案:一张表看差距

维度Selenium 全程操作页面本方案(仅登录用浏览器)
单次状态检查整页加载 + 渲染 + 元素定位,秒级量级(约,实测环境)1 次subpage请求,毫秒级往返(实测环境)
下单动作依赖按钮可点,渲染完才可能出手轮询到状态变化立即发请求,不等渲染
常驻内存一个 Chrome 实例(约 200 MB 起步,实测环境)纯 Python 进程 + requests 连接池
登录次数每次运行都要扫码或输密码Cookie 持久化后 0 次,失效才重登
接口变更适应找按钮、改选择器重跑参数提取正则,或更新 signcode.js

数字除标注外均为代码结构层面的定性描述与常见量级估计,具体耗时取决于网络和机器配置。

五、最小上手路径

git clone https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase pip install -r requirements.txt

下载与系统匹配的 chromedriver,按 README 要求重命名为chromedriver_windows/chromedriver_linux/chromedriver_mac并放在项目根目录,然后改 5 个字段:

self.login_id: str = 'account' # 大麦网登录账户名 self.item_id: int = 610820299671 # 商品id(不同城市/场次不同) self.viewer: list = ['viewer1'] # 大麦已登记的观演人姓名 self.buy_nums: int = 1 # 购票数量,须与观演人数一致 self.ticket_price: int = 180 # 目标票价

大麦商品页地址栏中的 item_id,即脚本的商品 id 配置来源

运行:

python Automatic_ticket_purchase.py # 账号密码登录 python Automatic_ticket_purchase.py --mode qr # 扫码登录

六、常见坑与调优

  • 现象:提示"登录失败,请检查登录账号信息"。成因:cookies.pkl里的会话已过期,但文件还在,run()会优先走它。处置:删除cookies.pkl,强制重新登录并重新落盘。

  • 现象:打印"请检查输入的观演人信息与大麦网观演人信息是否一致"。成因:viewer里写的名字与大麦"常用购票人"登记名不完全相等,step3_submit_order() 用集合交集校验,一个字符对不上就返回False。处置:逐字核对大麦页面登记的姓名,含空格也要一致。

  • 现象:解析异常,提示"获取购买必备参数异常,请重新解析response返回的参数"。成因:get_api_param() 的正则依赖特定版本的 CDN JS 结构,官方发版后匹配落空。处置:打开g.alicdn.com上最新的vendor.js,按新的结构重改两段正则。

  • 现象:选座接口返回签名错误。成因:sign的输入含毫秒时间戳,系统时钟与服务器偏差过大会校验失败。处置:校准本机时间,再确认signcode.js与线上算法是否一致。

  • 现象:长时间紧密轮询后请求被风控拦截。成因:主循环在"即将开抢"阶段是continue紧循环(见 run()),无请求间隔,高频访问同一接口容易触发频率限制。处置:自行在循环中加随机休眠,把频率压到服务端容忍范围内。

七、边界与合规

先说清楚能做什么、不能做什么:

  • 只支持抢指定价位的票,选座暂不支持连坐,V2.1 是当前上限;
  • README 首页已声明"已停止维护,大部分购买方式已迁移至手机端,需配合抓包处理,暂无更新计划"。照搬代码大概率需要按移动端接口自行改造;
  • 依赖锁得很旧:selenium 3.141.0、requests 2.24.0、beautifulsoup4 4.9.3,新项目环境里可能遇到兼容问题。

合规层面必须明确:脚本要求填写账号密码,cookies.pkl里是完整登录态凭证,属于敏感数据,不要提交到代码仓库或分享给他人。自动化高频请求可能违反平台服务条款,用于倒卖票则涉嫌违法。仓库以 MIT License 提供,仅限个人学习研究,商业用途风险自担。

把页面操作换成接口调用,省掉的是渲染等待;要还的账,是接口一变就得重新逆向的维护成本。

【免费下载链接】Automatic_ticket_purchase大麦网抢票脚本项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进