
简介大麦网抢票脚本.rar 是一份基于 Python 与 Selenium 的自动化抢票工具面向具备一定 Python 基础、希望提升大麦网热门演出购票成功率的用户。压缩包体积约 5KB总共 2 个文件抢票脚本.py 实现浏览器模拟登录、定时刷新票池、点击购票按钮、填写订单等核心逻辑user_info.txt 用于存放账号或 Cookie 等敏感信息需在运行前自行配置并注意隐私安全。该脚本源自知乎项目原内容经过改动、结构较乱作者特意提示“以参考为主”实际使用时应结合最新页面结构和实测教程逐段调试防止因网站改版或反爬策略失效。资源目前已有 22067 人学习下载适合想研究 Selenium 自动化流程、学习抢票程序骨架或二次开发购票逻辑的读者可作为快速入门的示例模板从中获取定位元素、模拟操作、异常处理等实用思路。1. Python抢票脚本到底做了什么把人力操作压缩成毫秒级请求某票务平台的演出票有多难抢抢过的人都有体会倒计时一结束页面先卡两秒等你能点进去所有票档已经变灰。而这份“抢票脚本”的思路不是让手更快而是把人工刷新、选票、提交订单这一串操作替换成一段能直接命中下单接口的Python程序。它不是外挂也不绕过购票规则只是把操作节奏做到机器级别。这份资源适合两类人一类是真心想抢票但手速跟不上普通用户学会改配置就能用另一类是研究自动化下单与接口逆向的开发者可以拿它当样本去看登录态维护、请求频控和重试策略。2. 抢票脚本的核心逻辑登录态、主循环与下单回退2.1 登录态Cookie注入为什么比账密登录稳先聊第一个绕不开的环节登录态。票务平台的抢票接口基本都要登录因为实名制购票要求用户身份绑定在订单上。换句话说脚本第一步要解决的是“让平台认为你是一个已登录用户”。常见做法有两种账号密码登录和扫码登录。账号密码登录最容易写但翻车率也最高——平台在密码登录环节普遍叠加了滑块验证和异地登录风控纯requests模拟几乎过不去。扫码登录则更稳脚本在终端或浏览器窗口打印二维码你用手机App扫一下脚本把登录后返回的Cookie落盘存下来之后的每次请求都带着这份Cookie。我一般会优先选扫码登录还有一个原因它不碰短信验证码不会因为同一设备频繁登录而触发风控。# login.py 扫码登录并把 Cookie 落盘方便下次直接复用 import time import requests def scan_login(session, login_url): 返回登录后的 Cookie 字典60 秒内未扫码则抛异常 resp session.get(login_url).json() qr_token resp[qrToken] # 二维码会话令牌 print(请在手机 App 中扫描以下二维码登录) print_qr(resp[qrContent]) # qrcode-terminal 库负责在终端画码 for _ in range(60): check session.post( CHECK_API, json{token: qr_token}, timeout3 ).json() if check[status] ok: cookies session.cookies.get_dict() save_cookies(cookies) # 写成 json 文件供 buy.py 加载 return cookies time.sleep(1) raise RuntimeError(扫码超时请重试)这段代码里有几个值得注意的参数qrToken是扫码会话的标识qrContent是二维码内容CHECK_API是轮询确认登录状态的接口地址。真实平台里的接口字段名可能不同但流程都是“获取二维码 → 轮询 state → 拿到Cookie”的同一套框架。save_cookies在资源包里通常是一个简单的文件写入函数序列化成JSON后下次运行直接读文件避免每次抢票前都掏手机扫码。Cookie复用不是无损的它有过期时间而且一旦账号在另一个设备登录旧会话会被顶掉。所以脚本里应当有一个load_cookies()加校验的逻辑如果加载的Cookie请求一个轻量用户信息接口返回未登录就自动回退到扫码流程。这个细节很多简化版脚本都不处理导致很多人开抢前才发现登录态失效属于典型的“毁在起跑线”。2.2 抢票主循环时间校准、重试节奏与请求头抢票脚本真正值钱的部分在主循环。开售瞬间服务器受理请求的先后可能只差几百毫秒所以这个循环里藏了三个关键点时间基准、请求体、重试节奏。先说时间基准。本机时钟与服务器时钟经常有偏差直接把配置里的target_time当成开抢点脚本会提前或推迟发请求。提前发请求会被当成非法访问推迟发就等于把票让给别人。常见做法是先请求一次平台的服务器时间接口计算本地与服务器的时钟偏移量用这个偏移量校准开售时间戳。# timer.py 计算本机与服务器时钟偏差避免抢票窗口偏差几百毫秒 import time import requests def get_server_offset(session, time_api): t0 time.time() * 1000 # 发送前本地时间 server_ms session.get(time_api, timeout2).json()[serverTime] t1 time.time() * 1000 # 接收后本地时间 network_delay (t1 - t0) / 2 # 用往返时间估算单程网络延迟 return server_ms - (t0 network_delay) # 正数服务器更快负数本地更快 def now_corrected(offset_ms): return time.time() * 1000 offset_ms这里用往返时间的一半估算单程延迟是最粗糙也最常用的办法。严格一点的做法是连续请求三次取最小往返但抢票场景里服务器时间接口响应本来就快一次足够。get_server_offset返回的偏移量加上本地时间就是修正后的当前时间。我建议在开抢前5分钟校准一次开抢前10秒再校准一次因为网络抖动会让第一次的估算偏掉几十毫秒。主循环本身不复杂难点在容错。一个能扛住并发返回的循环框架是这样的# buy.py 抢票主循环定时等待、限次重试、失败退避 import time import requests offset get_server_offset(session, TIME_API) def rush_buy(session, params, start_ms, max_retry12, interval0.3): while now_corrected(offset) start_ms: time.sleep(0.02) # 开售前空转保持会话不中断 for attempt in range(max_retry): try: resp session.post( ORDER_API, dataparams, headers{referer: https://detail.xxx.com/}, timeout2, ).json() if resp.get(success): return resp[data][orderId] # 抢到订单号进入人工支付阶段 if resp.get(errorCode) 429: # 被限流退避时间加长 time.sleep(interval 0.3) else: # 未开售、库存不足等错误码 time.sleep(interval) except requests.Timeout: time.sleep(interval) # 超时不一定失败可能订单已创建 return None参数说明start_ms是校准后的开售时间戳max_retry建议设置在10到15之间再多会明显触发风控interval在0.2到0.5秒之间做随机浮动更贴近真实用户。referer必须带平台会校验请求来源页不带Referer的下单请求被识别为脚本的几率非常高。超时分支要特别理解请求超时并不代表失败极可能是订单已经创建但响应没传回来所以超时后不要立刻放弃等一两秒再查询订单状态。下单请求的params结构各家不同但核心字段基本一致itemId、performId、skuId、buyerIds、count。资源包里通常把这几个字段从配置读入再拼成请求体字段顺序有时候也会影响签名校验所以如果平台返回签名错误先检查字段顺序和编码格式。errorCode含义处理策略429请求频率超限拉长退避随机延迟450未开售继续重试直到开售460库存不足快节奏重试等回流票470票档ID失效停止重试重新抓取skuId这张错误码表是我在调试时自己整理的不同平台码值有差异但处理思路一样先看码再决定是继续重试还是停下来修配置。2.3 下单之后脚本只负责创建订单支付必须留给人工主循环返回订单号之后脚本的任务就结束了。很多人会把自动支付也写进去我强烈不建议。原因有两层第一支付环节涉及免密协议、短信验证和支付密码自动化操作很容易触发支付风控第二票务平台的订单创建后一般保留几分钟的支付窗口留这个时间给人眼确认观演人、场次和票价是最安全的做法。抢错场次还能取消重来这个“后悔药”千万别用脚本替你做决定。# notify.py 抢到订单后的通知入口 def notify(order_id, ticket_info): print(f\a[抢票成功] 订单号 {order_id}) print(f场次: {ticket_info[time]} 票档: {ticket_info[sku]} 张数: {len(ticket_info[buyers])}) print(请在 5 分钟内打开手机 App 完成支付超时订单自动释放)这个notify函数在资源包里可以替换成任何你喜欢的通知方式本地响铃、企业微信机器人、Server酱推送都行。核心思路只有一个——把“抢到订单”和“完成支付”分成两个独立动作前者交给机器后者保留给人。这也是判断一个抢票脚本是否专业的分水岭把支付硬写进脚本的通常是对风控理解不足的产物。3. 把脚本跑起来环境、配置与一次干净的模拟3.1 环境准备Python版本与依赖安装资源包里的脚本基于Python。我在3.9和3.11上都跑过常见的依赖是requests、selenium、qrcode-terminal、retrying。其中requests负责下单请求selenium是备用的浏览器自动化方案qrcode-terminal负责在终端打印登录二维码。建议用虚拟环境隔离避免污染系统Python。python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install requests selenium qrcode-terminal retrying装完后先验证requests能正常导入再跑python login.py做一次扫码登录。这一步能提前暴露两个问题一是终端打印机不支持二维码字符需要改用浏览器窗口显示二维码登录二是网络环境访问平台接口超时需要确认本机网络是否存在代理或防火墙拦截。这两个问题如果等开抢前才发现基本没有补救时间。3.2 修改配置itemId、skuId、buyerIds 从哪来新手最容易卡在配置上因为每个ID都不是凭空来的。资源包里通常有一个config.py参数含义大致如下CONFIG { item_id: 720123456, # 演出详情页 URL 中 ?id 后的数字 sku_id: 1204356789, # 票档 ID内场/看台各有不同 perform_id: 7800123, # 场次 ID一场演出可能有多个开演时间 buyer_ids: [10023456789, 10023456788], # 观演人 ID实名购票必须 target_time: 2025-07-12 10:00:00, # 开售时间以平台公告为准 max_retry: 12, interval: 0.3, time_api: https://api.xxx.com/gettimestamp, # 服务器时间接口 order_api: https://api.xxx.com/order/create, # 下单接口 }获取这些ID最直接的方式是浏览器开发者工具。打开演出详情页按F12切到Network面板随便点一个票档找到对应的XHR请求看请求参数里携带的字段itemId是演出项目performId是场次skuId是票档buyerIds是观演人。平台界面上显示的是“内场1280”或“看台480”但后端只认一串数字ID。这里有一个我踩过很多次的坑skuId不是长期不变的。平台每次开票前都可能重新生成票档ID昨天抓到的ID今天开售时可能已经失效。所以开售前10分钟必须重新抓一次。这个习惯救了我不止一次后面避坑章还会展开说。3.3 先跑模拟用本地接口验证主循环逻辑不要拿真实开售时间做第一次试运行。我每次拿到新脚本都会先在本地起一个mock服务模拟平台的下单接口和错误码把主循环、重试、退避这些逻辑先跑通。这一步能过滤掉大部分低级错误。# mock_server.py 本地模拟下单接口前3次返回库存不足 from flask import Flask, request, jsonify app Flask(__name__) count 0 app.route(/order/create, methods[POST]) def create_order(): global count count 1 if count 3: # 故意失败几次验证重试逻辑 return jsonify({success: False, errorCode: 460}), 200 return jsonify({success: True, data: {orderId: TEST2025}}), 200 if __name__ __main__: app.run(port5001, debugFalse)把config里的order_api改成http://127.0.0.1:5001/order/create再把target_time设成当前时间加30秒运行主循环。你会看到脚本发4次请求前3次拿到460错误码后继续重试第4次拿到订单号。如果输出符合这个预期说明时间校准、重试节奏、订单返回解析都没有问题如果中途出现异常对比日志很容易定位是循环写法还是请求参数的问题。[00:00:00.120] attempt1 errorCode460 库存不足 [00:00:00.430] attempt2 errorCode460 库存不足 [00:00:00.740] attempt3 errorCode460 库存不足 [00:00:01.050] attempt4 orderIdTEST2025 抢票成功模拟通过之后再切回真实接口成功率会高很多。切换时只需要把order_api改回平台地址同时把target_time改回真实的开售时间。4. 避坑指南登录失效、限流、验证码与票档ID变动4.1 五个高频坑现象、原因、解决抢票脚本写出来容易稳定运行难。我整理了几条最常见的翻车记录每条都按“现象→原因→解决”来写你可以直接对照排查。第一次是本机时间比服务器快了200毫秒。现象是脚本在开售前就发出了请求平台返回“活动未开始”。原因是我没有做时间校准直接用本机时间去触发循环。解决方法是跑一次get_server_offset并在主循环里用修正后的时间戳。从那次以后我每次开售前都会校准两次一次提前5分钟一次提前10秒。第二次是Cookie失效。现象是脚本运行没多久下单接口返回401未登录。原因是Cookie过期或者账号在其他设备被登录把当前会话顶掉了。解决方法是每次启动时先加载Cookie并请求一个轻量接口验证登录态失效就自动退回到扫码登录。这个校验逻辑值得单独写在主函数开头别省。第三次是高频请求被限流。现象是前5次请求正常第6次开始连续返回429。原因是我把重试间隔设成了固定0.2秒平台的风控引擎识别到了规律性请求。解决方法是把间隔改成随机浮动用random.uniform(0.2, 0.5)生成每次的退避时间同时轮换部分请求头字段。第四次是票档ID变了。现象是脚本报“参数不合法”而网页端明明还能看到余票。原因是开售当天平台重新生成了skuId我还在用昨天抓到的旧值。解决方法是开售前10分钟重新抓取一次票档ID并且把抓取动作写进脚本的启动流程而不是手工粘贴。第五次是观演人数量超限。现象是下单失败提示“该场次每单限购2张”。原因是我在配置里传了4个观演人而场次规则限制了单笔订单人数。解决方法是先读取场次规则超限时自动截断到允许的数量而不是直接报错退出。这条对帮朋友抢票的场景特别实用。4.2 抢票的“玄学”接口预热与首次请求成本除了上面五个可复现的坑抢票还有一个说不清的部分。同一套代码有人一次就成有人一开抢就卡死在第一步。我的观察是大部分“玄学”其实来自首次请求的成本开售瞬间平台会批量推送一大波活动数据如果你脚本里第一个请求就是下单接口很容易被当成异常流量。常见做法是提前几秒开始轮询详情页接口让会话保持活跃再在开售瞬间切换到下单接口。这个预热动作不保证成功但不做的话失败概率明显更高。4.3 验证码出现时怎么办人工介入窗口图形验证码和滑块是脚本最头疼的对手。脚本可以识别简单滑块但平台升级后经常失效。我一般会在脚本里预留一个人工介入窗口当检测到验证码字段时脚本停止自动重试播放提示音并弹出浏览器窗口等待人在30秒内手动完成验证验证通过后再继续下单流程。这个做法牺牲了一点速度但比盲目自动过码稳定得多。自动打码平台也能接但费用和稳定性是变量不建议把它作为首选方案。5. 进阶优化把脚本变成可复用、可排查的小工具5.1 日志落盘下次翻车时不用靠猜抢完票日志早扔了追悔莫及。我习惯把每次运行的关键节点写进日志时间校准偏移量、每次重试的错误码、最终结果。这样下次失败时有据可查不用对着黑匣子猜。用logging的FileHandler落盘即可每天一个文件保留七天。5.2 随机延迟与请求指纹别让风控一眼认出你把固定的重试间隔和请求头参数随机化是最廉价的风控对抗手段。User-Agent从真实浏览器的UA池里随机选重试间隔用均匀分布而不是固定值请求之间偶尔模拟一下鼠标停留的停顿。这个小改动能把被限流的概率降低一截亲测有效。5.3 自检清单开抢前十分钟固定检查项我最终把抢票流程收敛成一张固定检查单校准服务器时间、校验并刷新登录态、重新抓取票档ID、启动mock模式验证下单链路、切回真实接口。五个动作十分钟内完成。如果你拿到这个资源包先别急着把真实开售时间填进config第一件事是跑mock服务把主循环走通再按检查单过一遍配置。我之前吃过一次亏把票档ID写死在配置文件里开售当天连报五次“参数不合法”眼睁睁看着票被抢完。从那以后每次开抢前我都强制走一遍这张清单再也不敢省掉重新抓取票档ID那一步。希望帮到你。本文还有配套的精品资源点击获取