大麦网抢票脚本技术拆解:从抓包到下单的完整实现 📅 发布时间:2026/9/16 14:29:25 👁 浏览次数: 简介面向大麦网演唱会等演出抢票场景的自动化辅助脚本适合有一定Python基础、希望提升抢票效率的个人用户。脚本基于Python与Selenium驱动浏览器完成登录、选座与提交订单等关键操作能有效缓解手动刷票易秒空、易错过的问题需要自行安装与Chrome版本兼容的ChromeDriver并确保Python3环境。压缩包共6个文件包含Python主程序、JSON配置、YAML工作流配置、Markdown使用说明及开源许可等整体仅9KB结构紧凑非常适合学习自动化控制与二次修改目前已有101人学习下载。脚本首次运行会自动唤起浏览器登录大麦并保存CookieCookie过期或失效时需删除cookies.pkl重新登录使用前需完成大麦账号实名认证并至少添加一位购票人信息否则下单环节无法通过。读者可借此理解Selenium自动化、Cookie持久化及抢票流程设计并在基础上扩展出适合自己需求的版本。1. 大麦网抢票脚本到底在抢什么下单链路与脚本边界手动抢票时从点击购买到提交订单至少需要两秒脚本直接把下单请求发给大麦网接口耗时能压到几百毫秒。抢票竞争本质上就是请求到达顺序的竞争脚本赢在提前构造好参数、等待开票瞬间发出。这篇文章拆解实现一个可运行的大麦网抢票脚本所需的全部环节抓包定位接口、维持登录态、并发控制、订单提交最后讲怎么把脚本打包成zip压缩包分发。适合写过Python、想理解接口调用和并发控制的开发者也适合做秒杀系统或反爬的工程师参考。需要提醒的是用脚本抢票违反平台规则可能封号这里只做技术讨论。2. 动手前先搭环境从zip包到抓包准备2.1 解压zip压缩包后的文件结构与依赖清单从网上下载的“大麦网演唱会演出抢票脚本.zip”往往先卡在解压。很多作者会设置压缩包密码提示语写着“关注公众号回复关键词获取”这时候不要在搜索引擎里找“zip压缩包密码破解工具”因为对于ZipCrypto格式还有机会对于AES-256加密的zip暴力破解基本不可能。先用7-Zip看一眼加密方式命令是7z l -slt 大麦网抢票脚本.zip观察输出里的Crypto AES-256还是ZipCrypto。如果是AES-256正确做法是回下载页找密码说明而不是浪费时间破解。另外如果解压时7-Zip报error read zip archive或invalid zip archive: could not find eocd说明文件下载不完整需要重新下载常见于用网盘客户端下载中断的情况。一个正常的抢票脚本压缩包解压后通常有这几个文件文件名作用main.py抢票主入口包含轮询和下单逻辑config.py演出ID、票价、场次、抢票时间等配置login.py登录和Cookie保存逻辑requirements.txtPython依赖列表README.md使用说明和参数解释很多用户拿到压缩包后发现里面已经有一个编译好的exe而不是.py脚本。这时要警惕因为你看不到源码它很可能捆绑了盗号木马。真正的技术交流应该发布源码而不是二进制所以尽量找有Python源码的版本。如果压缩包里既有.exe也有.py优先看.py自己打包。有了requirements.txt先创建虚拟环境再安装依赖python -m venv venv source venv/bin/activate # Windows下用 venv\Scripts\activate pip install -r requirements.txt常见的依赖有requests、aiohttp、pycryptodome、selenium。requests负责同步请求aiohttp用于异步并发pycryptodome用来处理大麦的加密参数selenium在需要扫码登录时才会用到。不要直接把这些包装到系统Python环境虚拟环境能避免版本冲突。2.2 用中间人工具抓取大麦网关键接口脚本要工作必须先知道创建订单的接口地址、参数和返回结构。常见做法是在电脑上启动中间人服务比如Charles或Fiddler让手机的请求转发到电脑这样能看到大麦App发出所有HTTP请求。具体步骤电脑和手机连同一个Wi-Fi手机设置HTTP转发到电脑的8888端口。在中间人工具里开启SSL解密添加对大麦域名比如*.damai.cn的规则注意大麦相关的域名还有damai.net两个都加比较稳妥。手机打开大麦App浏览目标演出的详情页、场次列表、票档列表但不要真的下单。回到中间人工具按路径过滤找包含order、perform、sku、create的请求节点。重点看两个接口获取演出信息的接口和提交订单的接口。前者返回场次、票价、票档的ID关系后者在点击“立即购买”并确认订单时触发。需要把它的完整URL、请求头、请求体、响应体记录到本地。后续代码中的下单URL和字段名都从这里来。注意接口地址可能会随版本更新变化不要照抄网上的旧教程以你自己抓到的为准。拿到接口后建议先用Postman或者curl复现一遍请求确认可以直接请求成功。因为大麦的部分接口会校验Content-Type、x-requested-with等头部用Postman可以快速验证这些头的组合。验证完成后再把请求导出为Python代码比直接手写要可靠得多。2.3 登录态与Cookie持久化大麦的下单接口要求登录状态。脚本里用requests.Session()维持连接但登录过程中有滑块验证无法完全自动化。我一般先用浏览器或手机完成一次登录然后把Cookie序列化到本地文件之后脚本每次启动时加载。用Python的pickle可以保存CookieJarimport pickle import requests s requests.Session() # 手动登录以后把session的cookies保存起来 with open(cookies.pkl, wb) as f: pickle.dump(s.cookies, f)下次运行脚本时直接加载with open(cookies.pkl, rb) as f: s.cookies pickle.load(f)需要注意几点Cookie有过期时间大麦的登录态通常几天到一个月有效建议开抢当天重新生成一次如果中间人工具看到某个请求返回401或跳转登录页说明Cookie失效需要重新扫码。用pickle保存的Cookie只适用于同一Python环境换机器可能会因为缺失部分sessionId字段而失效所以不要把cookies.pkl算作可移植的压缩包内容。如果想少一步手动导出Cookie可以用selenium启动浏览器让用户主动扫码之后读取Cookie。示例from selenium import webdriver from selenium.webdriver.chrome.options import Options import requests opts Options() opts.add_experimental_option(detach, True) driver webdriver.Chrome(optionsopts) driver.get(https://login.damai.cn) input(扫码完成后回车...) cookies {item[name]: item[value] for item in driver.get_cookies()} s requests.Session() s.cookies requests.utils.cookiejar_from_dict(cookies) with open(cookies.pkl, wb) as f: pickle.dump(s.cookies, f) driver.quit()这段代码先通过selenium打开真实浏览器用户扫码登录后把浏览器里的cookie取出来转换成requests能用的CookieJar并保存。注意detach参数让浏览器在脚本结束后不自动关闭方便你先观察登录状态。如果登录时遇到滑块验证一个技巧是先用手机App手动登录然后用中间人工具从App的流量里提取Cookie这样得到的Cookie字段比浏览器版更全因为App端会携带额外的token例如umToken、dmtDeviceId。这些字段对下单接口能否通过风控很重要。3. 核心抢票逻辑从选场次到提交订单的代码实现3.1 场次、票价与票档的参数映射大麦演唱会详情页的数据结构通常是一个嵌套JSON。以抓包到的内容为例演出详情接口会返回{ perform: { performId: 120100001, itemId: 99000001, name: 某歌手巡回演唱会-北京站 }, priceList: [ {priceId: 201, name: 看台399元, skuId: 1001, stockStatus: 0}, {priceId: 202, name: 内场1599元, skuId: 1002, stockStatus: 0} ] }这里几个关键字段的用途需要分清参数来源说明performId演出详情接口唯一标识一场演出itemId演出详情接口同一城市下多个场次priceId票价列表价格档位skuId票档列表真正下单使用的ID抢票脚本需要提前把目标场次的performId、skuId写进配置文件开票时不等待详情接口返回直接构造下单参数。如果接口返回的stockStatus是0表示有货1表示无货。对于大多数演唱会开票后几秒内就会售罄所以直接下单往往比轮询详情更高效。但有一种情况例外部分场次的票是分批次放出的比如每5分钟放一点。这时脚本需要在开票后的长时间内持续轮询库存查询接口。库存查询接口返回的字段可能是stockStatus或quantity你可以在抓包里搜索“stock”找到。轮询时注意控制频率建议每秒不超过2次否则后端会直接返回脏数据。我见过有人用每秒10次的频率轮询结果被风控返回固定的false反而错过了放票窗口。3.2 高并发下的抢票请求协程与并发数控制为什么不用多线程Python的GIL限制下线程切换开销高而且requests的响应等待会让线程阻塞。协程在等待IO时主动让出控制权适合这种高I/O等待的场景。如果你更熟悉asyncio可以在同一个事件循环里同时执行轮询和下单但注意不要让两个任务同时操作同一个Session。同步的requests在等待响应时CPU闲置效率不够。常见做法是改用aiohttp异步库在单线程内发起多个并发请求。但并发数不是越大越好大麦风控系统会检测同一IP的请求频率并发太高会触发滑块验证甚至暂时封禁。我一般把并发数控制在5到8结合50毫秒左右的轮询间隔。下面是一个简化的异步抢票示例import aiohttp import asyncio import time ORDER_URL https://order.damai.cn/api/order/create async def submit_order(session, order_data): # 为每个请求生成独立流水号避免幂等冲突 order_data[requestId] str(int(time.time() * 1000)) try: async with session.post(ORDER_URL, jsonorder_data, timeout3) as resp: result await resp.json() if result.get(success): print(下单成功, result[orderId]) else: # 库存不足或风控时打印错误码 print(下单失败, result.get(code), result.get(msg)) except asyncio.TimeoutError: print(请求超时跳过本次) async def main(): order_data { performId: 120100001, skuId: 1001, cityId: 1, count: 1 } async with aiohttp.ClientSession() as session: while True: tasks [submit_order(session, order_data.copy()) for _ in range(5)] await asyncio.gather(*tasks) # 轮询间隔随机抖动避免周期性被识别 await asyncio.sleep(0.05 0.02 * (time.time() % 1)) asyncio.run(main())代码里最关键的是requestId参数。如果每个任务用同一个requestId服务器会认为是重复提交而拒绝。另外timeout设为3秒因为抢票时商家响应很快超过3秒大概率已经无货或卡住没必要继续等待。order_data.copy()很重要因为每个协程会修改requestId如果传同一个引用task之间的数据会互相覆盖。3.3 订单提交与返回码处理大麦下单接口的返回码在不同版本中不完全一致需要通过抓包总结。常见的处理逻辑如下表返回码含义处理策略0 或 200下单成功记录订单号停止轮询1库存不足继续下一次轮询2票价变动重新拉取票价列表3触发滑块验证暂停脚本人工介入401登录过期退出并重新登录实际代码中建议把返回码和HTTP状态码分开判断。比如HTTP 200但请求体里code是1说明业务失败。可以封装一个函数def handle_result(result): code result.get(code, -1) if code in (0, 200) and result.get(success): return SUCCESS if code 1: return RETRY if code 3: return SLIDER return UNKNOWN还有一种情况是下单接口返回errorCode而不是code。写代码时不要把字段名写死建议先打印一次完整返回内容再用result.get(errorCode, result.get(code))这种兼容方式读取。如果返回值是“SLIDER”说明需要人工完成滑块验证脚本里可以暂停并播放提示音等待用户介入。4. 参数调优与反爬对抗把脚本调到能用的状态4.1 轮询间隔、超时与重试策略抢票脚本的可用性往往取决于参数设置。过快的请求会把IP送进风控白名单过慢又抢不到。我的常用配置如下参数推荐值说明connect_timeout1秒连接建立超时read_timeout3秒读取响应超时轮询间隔50~100毫秒加随机抖动最大重试次数3次指数退避1s、2s、4s单IP并发5~8超过容易触发验证对于重试可以用简单的指数退避import time def retry_with_backoff(func, max_retries3): for i in range(max_retries): result func() if result RETRY: time.sleep(0.2 * (2 ** i)) continue return result return FAILED注意这里的退避只针对库存不足不针对超时。超时意味着链路问题继续重试只会加重负载。随机抖动可以这样实现time.sleep(random.uniform(0.05, 0.1))而不是固定值。固定间隔的请求在服务端日志里看起来像一个轨道运行的时钟很容易被识别为机器。判断是否被风控不要只看返回码。有一次我发现脚本一直返回库存不足去抓包看发现同一个请求手动在浏览器里发可以正常返回有货后来才意识到是请求头里的X-Sign过期了。风控系统会故意在返回体里隐藏真实错误所以遇到“库存不足”要先确认是不是真的没货。4.2 设备指纹与风控字段的模拟大麦App请求头里有很多设备信息比如通过特定算法生成的X-Sign、Device-Id。如果直接用requests默认头几乎必被拦截。一个低成本的方案是从浏览器登录后的请求里复制完整的Headers头包括User-Agent、Referer、Accept-Language、sec-ch-ua等全部写进session。session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ..., Referer: https://detail.damai.cn/, Accept: application/json, Origin: https://detail.damai.cn, })这只能骗过简单的服务端校验。要模拟X-Sign签名必须逆向App的加密函数通常是通过Frida在Android端动态调试抓取难度较高。更省力的办法是使用大麦H5端的接口。下面是对比维度App端H5端接口签名X-Sign等复杂签名部分接口无签名或弱签名抓包难度需要绕过证书固定浏览器直接抓包登录方式扫码授权手机验证码风控强度高相对宽松所以如果你只是为了研究抢票机制优先跑通H5端把App端的签名问题放在后面解决。4.3 多账号与多IP的使用边界讨论多账号之前必须明确这是风控最严格的部分。大麦对同一IP关联多个账号有明确的设备指纹识别即使换浏览器也无济于事因为硬件层面的设备ID不会变。在真实抢票场景中一个IP下跑两个以上账号基本都会被判定为风险行为。有团队会使用多IP调度但这对个人来说成本很高而且IP池的质量参差不齐很多时候拿到的是已经被风控的IP反而拖累抢票速度。如果只是学习并发和接口建议最多一两个账号并让两个账号的请求错开200毫秒以上。不要把抢票脚本当作压力测试工具去轰炸接口否则账号被限制后连正常购票都会受影响。另外不要在同一台电脑上用多个浏览器无痕窗口模拟多账号Chrome的指纹信息仍然会暴露真实设备。大麦的风控会记录WebRTC的本地IP、canvas指纹等这些在无痕模式下也不会变。如果你真的要做多账号测试请使用多台独立的设备或手机上的不同应用分身但仍然有风险。5. 把脚本封装成可直接分发的zip小工具5.1 用PyInstaller打包并压缩成zip脚本调试完成后如果想让别人不用装Python也能运行可以用PyInstaller打包成单文件。命令如下pyinstaller -F main.py --name damai_grab-F表示打包成单个exe文件--name指定名字。调试时不要加-w保留控制台窗口才能看到日志输出。打包完成后dist目录里会出现damai_grab.exe。这个exe体积通常较大用7-Zip压缩一下7z a -mx5 damai_grab.zip dist\damai_grab.exe config.py README.txt-mx5是压缩等级介于速度和体积之间。如果后续修改了脚本必须重新打包不能手动改zip里的文件。如果想进一步减小体积可以先对exe用UPX压缩但注意有些杀毒软件会误报UPX壳需要权衡。5.2 压缩包密码与完整性校验给zip加密码时优先用7-Zip的AES-256格式而不是ZIP传统加密。传统ZipCrypto算法弱网上“zip密码移除工具”对它有概率直接破解。AES-256则不行但它的格式对7-Zip和WinRAR兼容Windows自带的解压器可能不支持。可以用命令行创建7z a -tzip damai_grab.zip dist\damai_grab.exe config.py -pYourPass_2025 -memAES256注意-memAES256指定加密算法。密码至少12位混合大小写和数字。如果别人下载后发现解压报error read zip archive优先检查文件是否下载完整而不是怀疑密码错误。发布前用7z t测试一下7z t damai_grab.zip顺便把exe的SHA256哈希写到README里让下载者能核对文件完整性避免被第三方篡改。Windows下可以用certutil -hashfile damai_grab.zip SHA256生成哈希。5.3 失败场景定位日志与抓包回溯脚本发出去后最常遇到的问题是大麦更新了接口字段导致订单提交失败。我在代码里会尽量把请求URL、响应体前500字符、耗时、时间戳写入日志。当用户反馈不工作时先看日志里是否有code3或401前者是滑块验证后者是登录过期。如果日志显示下单参数返回invalid parameter说明字段结构变了。这时需要用中间人工具重新抓包把新请求保存成har文件再和旧请求做对比。一条有效的技巧是使用jq规范化后做diffjq -S . new_request.har new.json jq -S . old_request.har old.json diff new.json old.jsondiff输出的差异行能直接告诉你哪个参数被删除、哪个被改名。这个技巧不局限于抢票脚本任何接口版本升级后的排查都能用。本文还有配套的精品资源点击获取