简介:面向Python学习者及有抢票需求的用户,这是一份自动化购票脚本源码包,以Python实现模拟登录、监控票务并自动提交订单,内置选座购买逻辑,适合参考网络请求、HTML解析与定时任务等实践。压缩包共10个文件,包含2个Python主程序与工具脚本、2张流程图/示例截图、1份Markdown说明文档、1个JS辅助文件及依赖清单,整体仅1.37MB,结构清晰便于快速上手。已有10806人学习下载。源码包提供完整的抢票实现代码与配置入口,涵盖登录参数、票价选择、座位筛选等模块,已实现选座购买、暂不支持连坐;同时附带流程图和界面示例图,帮助理解自动购票流程;README给出安装与运行指南,可直接在Python环境中部署试运行。对想掌握自动化脚本、应对验证码等反爬机制的开发者,是很好的参考项目。
1. 大麦网抢票脚本 Python 源码:不是外挂,是一套时序竞争工程
先说结论:大麦网抢票脚本 Python 源码,本质上不是某个神秘的“秒杀神器”,而是一套把账号登录、场次选择、座位勾选、订单提交串成流水线的自动化程序。它要解决的核心问题只有一个——在库存释放的瞬间,把请求尽可能早地送到服务器,同时绕过登录验证、风控校验和接口特征识别这几道关卡。适合的读者是有 Python 基础、愿意自己维护脚本逻辑而不是买成品、想搞清楚每一步在干什么的开发者。
需要泼一盆冷水:脚本并不保证百分百抢到,它能做的是把“看到有票再手动点”变成“余票出现后自动提交”,把点击延迟从人类的几百毫秒压缩到程序的上百毫秒。成功率取决于账号权重、网络延迟、并发窗口和验证码处理,四者缺一不可。
本文不会给你一份注释翔实到可以直接粘贴运行的完整源码,因为大麦网的接口参数和风控策略经常调整,任何固定版本都会过期。我会按最常用的技术路线,把整个脚本的骨架、关键参数、常见翻车点和调优方向拆开讲,你照着搭,再根据当天接口变化微调,才是一条走得通的路。
2. 从登录到下单:抢票脚本的技术链路与三大核心模块
2.1 会话保持与风控线索:requests 还是 playwright
写抢票脚本的第一步是选技术底座。常见做法是两条路线:纯 requests 方式和浏览器自动化方式。
纯 requests 方式直接模拟 HTTP 请求,优点是轻量、并发高、内存占用小,一个进程可以同时跑几十个会话;缺点是必须自己处理登录态、加密参数、请求头风控字段,一旦接口加了新的签名逻辑,脚本就立刻失效。浏览器自动化方式用 playwright 这类工具驱动真实浏览器,登录验证码、滑块拼图这类反爬手段基本能自动过,缺点是每个浏览器实例要占几百兆内存,并发起不来,而且窗口多了容易触发设备指纹风控。
我的经验是:脚本主体用 requests,验证码环节单独用 playwright 处理。登录时先用 playwright 打开浏览器、完成扫码或滑块验证、拿到带 cookie 的会话,然后把 cookie 导出给 requests 复用。这样既绕过了登录环节最难的验证码,又保住了后续高频请求的低延迟优势。如果你只抢热门演出、不需要多账号并发,全流程用 playwright 也没问题,但要把超时和重试参数调好。
2.2 场次与票档的选择策略:接口轮询与库存判定
登录态拿到之后,脚本的核心工作就是盯着目标场次的库存状态。大麦网 App 和网页版有各自独立的接口,网页版的接口相对稳定,但部分演出只开放 App 端抢票,这时抓包工具就派上用场了。
一般做法是先用抓包工具记录一次手动选择场次、票档、数量的完整流程,找到三个关键接口:场次列表接口、余票查询接口、下单接口。场次列表通常在页面加载时请求一次就够了,余票查询才是轮询的重点。轮询的时候不要每个循环都完整走一遍 HTTP 请求,而是要在循环外复用 requests.Session 对象,让连接复用 TCP 通道,减少握手开销。
库存判定这块有个容易踩的误区:不要只盯着“是否有票”这个布尔值,要看返回数据里的库存状态码。很多场次在开售前会返回“未开售”,开售瞬间变成“可售”,再往后变成“无票”,中间还有一个“余票紧张”的状态。脚本的轮询条件要写成只有当状态码处于可售区间才触发下单,否则继续循环。
2.3 订单提交时序:从余票探测到付款页的关键几秒
余票探测和下单之间,是整个脚本里最要命的时间窗口。库存释放后,大量用户同时提交订单,服务器会在几百毫秒内把库存锁给最快的一批请求。轮询到有票再发起下单请求,这中间多出的一次网络往返,可能就是成败的分水岭。
所以成熟一点的方案会把“探测”和“下单”拆成两个并行动作:一个协程在疯狂轮询余票,另一个协程在探测到可售状态的瞬间立即执行下单接口。下单接口的参数要在开售前就提前构造好,包括场次 ID、票档 ID、购买数量、收货人信息,不能等到拿到余票结果再去查一遍名单。
订单提交成功后,脚本一般会停在订单确认页或者直接引导到付款页。大麦的支付流程有独立的订单号生成逻辑,而且部分场次要求下单后几分钟内付款,否则自动释放。脚本要在提交订单后立刻轮询订单状态,拿到待支付状态就调用本地通知或者自动打开浏览器让用户手动付款,这一步不建议全自动,付款环节涉及资金安全,留给人来确认更稳妥。
3. 源码骨架:一个最小可用抢票脚本的分层实现
3.1 会话管理模块:cookie 的导入与复用
前面说了,验证码用 playwright 过,后续用 requests 跑。这块的代码就是把浏览器 cookie 导出来,转成 requests 能用的格式。一个最小实现大概是下面这样。
import asyncio import json from playwright.async_api import async_playwright async def get_cookie_from_browser(): # 用 playwright 打开浏览器,人工扫码或过滑块 async with async_playwright() as p: browser = await p.chromium.launch(headless=False) context = await browser.new_context() page = await context.new_page() await page.goto('https://example.com/login') # 等待用户手动完成登录,超时设为 120 秒 await page.wait_for_url('**/home', timeout=120000) cookies = await context.cookies() with open('cookies.json', 'w', encoding='utf-8') as f: json.dump(cookies, f, ensure_ascii=False, indent=2) await browser.close() if __name__ == '__main__': asyncio.run(get_cookie_from_browser())这段代码的核心是page.wait_for_url,它会阻塞直到页面跳转到登录后的首页。实际地址要按当天的页面跳转逻辑改,有些演出登录后留在原页面,那就改成等某个元素出现。cookie 存成 JSON 后,requests 的会话里直接循环 set 进去就行。
cookie 有两个要注意的地方:一是大麦的 cookie 里有设备指纹相关的字段,不能手动删掉,删了会被判定为新设备重新验;二是过期时间要看具体字段,有的几小时就失效,有的能撑几天,脚本开场前记得验证一次 cookie 有效性。
3.2 余票轮询模块:毫秒级探测的最小循环
轮询模块要控制节奏,不能像 while True 一样死循环,得带一个可以调节的间隔参数。下面这段是我常用的骨架。
import time import requests def poll_ticket_availability(session, target_sku_id, interval=0.1): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Referer': 'https://example.com/detail', 'Accept': 'application/json', } while True: try: resp = session.get( 'https://example.com/api/stock/query', params={'skuId': target_sku_id}, headers=headers, timeout=2, ) data = resp.json() stock_status = data.get('data', {}).get('stockStatus') # 状态码 1 表示可售,0 表示未开售,-1 表示无票 if stock_status == 1: print('可售状态,触发下单') return True except requests.exceptions.RequestException as e: print(f'轮询请求失败: {e}') time.sleep(interval)轮询间隔是个关键参数,设太短会打爆接口导致 IP 被限,设太长又抢不到热门的票。常见做法是先按 200 毫秒跑,如果连续几分钟没有一次请求报错,再把间隔降到 100 毫秒甚至 50 毫秒。这里的timeout=2也很重要,接口假死的时候不会把整个脚本拖死。
另外要注意,轮询接口的返回格式不是固定的。有的场次返回 JSON,有的返回一个带加密字符串的字段,需要二次解密。遇到这种情况,先抓包看一次返回数据长什么样,再决定怎么解析。别假设所有接口都是明文。
3.3 下单与验时模块:订单提交和防超卖重试
下单模块要处理的细节最多。参数签名、场次 ID 拼接、订单号回执验证,每一环都可能翻车。核心结构大概是下面这样。
def submit_order(session, item_id, sku_id, quantity=1, buyer_info=None): payload = { 'itemId': item_id, 'skuId': sku_id, 'quantity': quantity, 'buyer': buyer_info or {}, # 部分接口要求带上一个由服务器下发的 token 'token': session.cookies.get('order_token', ''), } headers = { 'Content-Type': 'application/json;charset=UTF-8', 'Origin': 'https://example.com', } resp = session.post( 'https://example.com/api/order/create', json=payload, headers=headers, timeout=3, ) result = resp.json() if result.get('success'): order_id = result['data']['orderId'] print(f'订单创建成功: {order_id}') return order_id else: # 常见失败码: 2001 库存不足, 2002 风控拒绝, 2003 参数错误 print(f'下单失败: {result.get("code")} - {result.get("message")}') return None这里的order_token不是常态存在的,很多场次由接口在某个前置步骤下发,需要在上一步的响应里取到并存在 session 里。下单失败后的重试要讲究策略:库存不足就别重试了,重试也是徒劳;风控拒绝必须停下来换登录态或换 IP;参数错误要回头检查上一步的数据是否过期。
延迟抖动也放在这个模块里做。每次下单请求前加一个random.uniform(0.2, 0.8)的随机停顿,避免多个请求的到达时间完全一致,这种“齐步走”的请求特征最容易触发风控。
4. 忘掉“秒杀”幻觉:抢票脚本的 5 个常见翻车点与排查思路
4.1 接口 403:缺了风控头信息
现象是脚本启动后,轮询请求大面积返回 403,浏览器里手动访问同一接口却正常。
原因是服务器的反爬网关在检查请求头里的User-Agent、Referer、Accept-Language,甚至是Sec-Fetch-Site这类浏览器自动带的字段。纯 requests 默认的请求头太干净,一眼就能认出是脚本。
解决方法是把抓包工具里浏览器发出的完整请求头复制下来,原样塞进 requests 的 headers 里。之后每次请求都会带上这些字段,403 的问题基本能解决。注意部分接口会对Referer做校验,跳转来源对不上也会拒绝。
4.2 显示有票却提交失败:库存二次校验
现象是轮询结果明明返回了可售状态,但下单接口总是返回“库存不足”或“手慢了”。
原因是余票查询接口和下单接口之间隔了几百毫秒,而在这段时间里库存已经被别人的请求锁定了。查询接口的数据是近似的,下单接口才是最终裁决。
解决方法是把轮询间隔进一步压缩,同时在下单接口的 payload 里带上查询接口返回的库存版本号。有些后端支持“版本号校验”,如果版本号对不上就代表库存已经变化,这时候要么重新查库存,要么放弃本次提交。盲目的连续重试只会加重风控标记。
4.3 验证码反复出现:设备指纹被标记
现象是同一账号在浏览器里登录只需一次验证,脚本里用 playwright 过完验证码后,下一次登录又弹验证码。
原因是服务器记录了浏览器指纹,包括 Canvas 指纹、WebGL 渲染结果、字体列表这些。playwright 每次新开浏览器实例,指纹都不同,就被当成新设备。
解决方法是固定使用同一个浏览器上下文目录,playwright 里可以设置launch_persistent_context,把浏览器数据目录固定下来,这样指纹就稳定了。另外也可以考虑在同一个上下文里完成登录和下单全流程,不要登录和抢票拆成两次浏览器会话。
4.4 脚本能跑但抢不到:连接没有预热
现象是脚本明明从开售前就开始轮询,但开售瞬间下单请求的耗时比其他人的请求多出一大截。
原因是 TCP 连接和 TLS 握手是在开售那一刻才发起的,多出来的这几百毫秒在全网竞争里非常致命。
解决方法是提前建立连接。脚本在开售前 10 分钟就开始请求商品详情页,用requests.Session把连接池填充好。部分实现还会提前调用一次余票查询接口,后续轮询直接复用同一条连接,省去每次请求的握手开销。
4.5 账号被限制购:单日下单频率触发风控
现象是脚本在某天抢到了票,第二天再用同一账号就提示“操作频繁”或直接要求人脸验证。
原因是大麦网的后台会统计每个账号的当日订单提交次数、接口调用频率和登录地变化。脚本高频轮询加上多次下单尝试,很容易触发限制。
解决方法是控制每个账号每天的脚本运行次数,同一账号不要反复上下线,也不要一天内抢多场演出。如果只是帮自己和朋友买,用脚本跑同一个账号风险最大,不如把账号分散开,每场用不同的账号执行。
5. 参数调优与边界控制:把成功率从“碰运气”拉到“高并发”
5.1 并发数量与线程模型怎么选
很多人一上来就开 50 个线程,指望靠量取胜,结果风控瞬间启动,账号全被限制。
常见做法是单账号不要开超过 3 个并发轮询协程。同一账号在同一场次的请求频率必须保持在每秒 20 次以内,超过这个阈值就会触发风控。多账号的并发可以放宽,但每个账号的 IP 要尽量固定,切换 IP 的动作会打断登录态,反而得不偿失。
线程模型上,我建议用asyncio而不是传统 threading。协程的切换成本低,单个进程可以挂几百个轮询任务,而且代码里天然适合做超时控制。如果你的网络环境有丢包,可以开一个线程专门清理超时的连接,避免协程堆积。
5.2 三个影响成败的延迟参数
第一个是轮询间隔。开售前用 300 毫秒跑,开售瞬间切到 50 到 100 毫秒,但必须在代码里设置一个最短间隔的常量,防止网络波动时循环失控。
第二个是请求超时。查询接口的超时建议设为 2 秒,下单接口设为 3 秒。超时设太长,脚本会卡在等待响应上,错过后续的请求窗口;设太短,正常的网络抖动会被误判为失败。
第三个是重试间隔。下单失败后的重试不能立即执行,我一般用random.uniform(0.5, 1.5)做随机退避。重试超过三次就直接放弃,把机会留给下一次轮询的触发。
5.3 接口参数中容易被忽略的字段
有些接口的参数里藏着动态 token、设备 ID 和匿名 ID,这些字段直接决定了请求能否通过后端校验。
最容易被忽略的是deviceId。纯 requests 方案没有浏览器环境,这个字段一般是通过某个 JS 函数生成的,直接硬编码进请求头会有过期问题。你可以用 playwright 打开一次页面,在页面上下文里执行对应的 JS 代码生成 deviceId,抓出来作为常量,半天内基本有效。
另一个是sign签名。部分接口要求在参数拼接后做 MD5 或 SHA256 摘要,密钥从某个 JS 文件里加盐生成。这个密钥每次版本更新都变,没有固定解法,只能靠抓包分析。
5.4 动态接口返回与降级预案
目前大麦网的反爬策略在往“动态接口返回”方向走,也就是说,你抓包看到的接口地址可能隔几天就换一次,返回字段的命名也会变化。脚本写好后不能放着不管,开场前花十分钟快速验证一遍接口是否正常,是个非常值的习惯。
如果 requests 方案某天完全跑不通,降级预案是切回 playwright 全流程。虽然慢,但接口变化对浏览器自动化方案的影响小得多。我一般会在脚本里做一层抽象:requests 方案作为默认路径,一旦连续失败超过五次,自动拉起 playwright 兜底。代码层面不需要做太复杂,两个类实现同一个下单方法就够了。
6. 从脚本到稳定赢面:一个值得养成的验收习惯
脚本写完之后,不建议直接拿真账号真演出去试,那样既浪费机会又容易触发风控。更稳妥的做法是先搭一个本地 mock 服务,把大麦网的几个关键接口按你抓包到的格式复现出来,然后让脚本去请求这个 mock 服务,验证全流程时序是否正确。
mock 可以用 Flask 起一个极简服务,接口路径和返回内容和真实环境保持一致。开售状态用一个后台线程去切换,比如设定 10 秒后从“未开售”变成“可售”,看脚本能不能在状态切换后的第一次轮询里触发下单。这个测试跑通了,再去真环境里做一次小成本验证。
我吃过大亏:有一版脚本在 mock 环境里跑得很顺,结果上了真环境后,下单接口返回了一个 mock 里没写过的错误码。查了半天,发现是请求头里少了一个由前置接口动态下发的字段。从那之后,我养成了一个习惯——每次开售前,先手动用浏览器跑一次完整的下单流程,抓包对比一下脚本发出的请求,确认没有遗漏再放脚本上线。
另外,抢票脚本这种代码有一个天然矛盾:你希望它越快越好,但大麦网的反爬系统也在不断升级。过快的请求、过整齐的频率、对不上号的头信息,都会让脚本在三分钟内失效。把参数调优当成持续的过程,而不是一次写完就结束。
这套方案值不值得投入,取决于你抢的演出热门程度和账号数量。如果你的目标场次经常是开售即罄的重磅演出,脚本能给你的只是比别人快零点几秒的优势,这个优势在强实名制和无条件退款规则面前,有时候并不足以保证成功。但如果目标是小众场次、冷门票档,脚本的自动化程度会大幅降低你守着页面反复刷新精力消耗,这种场景下投入产出比更高。
希望这篇实战拆解能帮到你。
本文还有配套的精品资源,点击获取