简介这是一份基于 Python 与 Selenium 实现的大麦网演唱会抢票自动化脚本面向需要抢购热门演出门票、又不想全程紧盯页面的用户也适合借此入门浏览器自动化操作。脚本通过解析 config.json 配置可设定目标日期、场次优先级、票价档位、实名购票人序号及购票数量同时支持多票价优先级、多位实名者组合选择能够有效解决手动刷新不及时、下单流程繁琐的问题。资源包共 5 个文件压缩后仅 43KB包含核心 Python 脚本、JSON 参数模板、README 说明文档、示例图片以及 GitHub Actions 工作流配置覆盖了从环境准备Python 3.6.3、selenium/requests/lxml 依赖、chromedriver 驱动到参数调试的完整参考信息使用时只需按说明调整对应参数即可。已有 3938 人学习下载对于希望快速跑通自动化购票流程或深入学习 Selenium 页面操控的读者是一份小而实用的现成脚本与配置参考。 作为一个平时喜欢看演出、又经常抢不到票的技术人我太懂那种“开票一秒陪跑一年”的感觉了。网上搜“大麦网抢票python代码”的人不少但我得先说句大实话真正能稳定跑赢人工的从来不是网速和手速而是对票务信息流的监控能力。这篇内容不会教你写一个违反平台规则、自动提交订单的“外挂”而是从抢票流程拆解出发手把手实现一个合规的“开票监控余票提醒”脚本让你不错过开票时间、不用守着页面反复刷新收到通知后动动手指完成下单。无论你是想学习Python爬虫和接口分析还是单纯想解决抢票焦虑这篇内容都值得看完。1. 先说结论为什么我劝你别做“抢票脚本”而是做“开票监控提醒”很多人一上来就搜“抢票脚本”满脑子都是“提交订单那一刻比谁快”。但如果你真的了解大麦网这类票务平台的抢票链路就会明白一个现实从点击“立即购买”到支付成功中间隔着库存锁定、风控校验、验证码、排队队列等一堆环节这些环节里有大量需要人为决策和身份验证的部分不是一个脚本能安全替代的。我见过有人做了全自动下单的脚本跑了几次之后账号被限流热门场次直接进不了购买页面甚至手机号被平台标记为异常。这里的底层逻辑是平台的风控系统会分析下单频率、设备指纹、IP行为、操作路径等维度脚本一旦出现“非人类操作特征”反而更容易被ban。所以从个人使用角度讲做一个**“信息监控工具”**的性价比远高于做一个“下单机器人”。所谓信息监控工具就是写一个程序定时去轮询目标演唱会页面解析出当前的票档状态、是否有票、开售时间是否到了然后把变化推送到你的微信或手机通知。它不做任何提交操作只做“消息搬运工”。这样做有几个好处不用在开票前半小时就一直刷手机程序替你盯着。开票瞬间你能在几秒内收到通知比大部分人打开App再点进详情页快很多。不触发平台的风控规则账号安全性高。而且从学习角度说这个项目的技术栈非常完整HTTP请求、Session和Cookie管理、JSON解析、定时任务、通知推送、异常处理全都用得到。学完之后你理解的不只是“抢票”而是“如何监控任意一个动态网页的状态变化”这套思路放到抢鞋、抢课、抢号、监控商品价格上都是通用的。2. 拆解抢票全流程真正能自动化的是哪一环想在技术上做对事情先要把业务流程拆明白。一场演唱会的典型购票流程是这样的用户在大麦网App或网页端搜索目标演出。进入演出详情页查看场次、票档、价格、开票时间。开票时间到达后点击“立即购买”。进入确认订单页面选择观演人、填写实名信息。提交订单系统进行库存锁定和风控校验。跳转支付页面完成付款。这里面“查询场次和票档状态”这一环本质是读操作每秒查询一次对服务器来说毫无压力也完全符合正常用户的行为——因为真人也会反复刷新页面看有没有余票。而“提交订单”“选择观演人”“支付”这几环是写操作涉及用户本人身份信息、支付密码、验证码在Web端模拟这个流程既复杂又容易踩红线。所以我的建议是自动化放在“查询”环节人工保留在“下单”环节。这也是本项目完全合规的根本前提。再往底层拆监控脚本的核心工作就是两件事拿到目标演出的数据包括演出ID、场次列表、票档、余票状态、开票时间。判断状态是否变化一旦从“无票/未开售”变成“有票/开售中”立刻触发通知。这里的关键在于“拿到数据”的方式。大麦网网页端的数据分发方式有两种一种是服务端渲染页面演唱会的部分基础信息直接在HTML里另一种是异步接口返回JSON数据余票状态、票档列表通常由XHR请求加载。我们需要做的是用浏览器的开发者工具分析出后者对应的接口URL和参数。这一步对新手来说是第一个门槛。很多搜索“大麦网抢票python代码”的人拿到一段过时的代码跑起来发现请求报错就是因为没有理解接口参数里的“演出ID”和“场次ID”是需要从页面里提取的而且不同演出的ID完全不一样。下面我详细讲整个实现过程。3. 从零实现一个合规的余票监控提醒脚本3.1 环境准备与抓包分析我默认你用Python 3.8以上版本。需要的库不算多requests发HTTP请求。datetime处理时间。time控制轮询间隔。json解析接口返回的数据。发送通知我推荐用PushPlus或Server酱企业微信或微信服务号推送它们都有免费的调用额度注册后拿到一个token然后用一行代码就能把消息推到手机上。安装依赖并确认版本pip install requests python -c import requests; print(requests.__version__)接下来做抓包分析。打开Chrome浏览器按F12打开开发者工具切到Network网络面板然后在大麦网搜索页找到目标演唱会进入详情页。操作过程中留意那些返回JSON的XHR请求。对大麦网来说关键接口通常是https://detail.damai.cn/item.htm?idxxxx这里的id就是演出ID。进入详情页后页面会请求一个类似https://mtop.damai.cn/h5/mtop.damai.wireless.item.detail/1.0/的接口返回的JSON里包含itemInfoData里面有场次列表、票档列表、开票时间等信息。注意请求这个接口需要带上完整的Cookie以及一些请求头字段。你需要从Chrome的开发者工具里找到这个请求右键选择“Copy as cURL”然后把cURL转换成Python requests代码。转换工具可以用curlconverter在线服务也可以手动翻。手动翻的时候重点关注Cookie、User-Agent、Referer这三个请求头。3.2 核心解析逻辑从HTML页面提取演出ID因为演出ID是动态变化的不同城市、不同场次的同一艺人演出ID都不同。最稳妥的方式是从详情页URL里提取。假设详情页地址是https://detail.damai.cn/item.htm?id745341228510那么745341228510就是演出的唯一标识。你可以用一个简单的正则把ID抠出来import re detail_url https://detail.damai.cn/item.htm?id745341228510 match re.search(rid(\d), detail_url) if match: item_id match.group(1) print(演出ID:, item_id)拿到演出ID之后再去请求详情接口才能拿到结构化的票档数据。这个ID是整个监控脚本的入参写死了换一场演出就不生效所以最好放在配置里。3.3 请求详情接口并解析余票状态我把请求封装成一个函数方便后面轮询调用。需要带上的请求头模拟浏览器行为import requests import json def fetch_item_info(item_id): url fhttps://mtop.damai.cn/h5/mtop.damai.wireless.item.detail/1.0/?itemId{item_id} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: fhttps://detail.damai.cn/item.htm?id{item_id}, Cookie: 你的Cookie } resp requests.get(url, headersheaders, timeout10) data resp.json() return data返回的数据结构比较深data.itemInfoData里有一个performanceList场次列表每个场次下面有一个performBases或者skuList票档列表。票档里有关键字段name票档名称比如“看台580元”。price价格。soldOut是否售罄。buyPermit是否允许购买。sellStatus售卖状态。解析逻辑我用一个示例代码展示重点是把“哪个场次的哪个票档可买”提取成一个可读字符串def parse_performances(data): try: item_info data[data][itemInfoData] except KeyError: return [] performances item_info.get(performanceList, []) results [] for perf in performances: perf_name perf.get(name, ) perform_id perf.get(performId, ) sku_list perf.get(skuList, []) for sku in sku_list: sku_name sku.get(name, ) sold_out sku.get(soldOut, False) buy_permit sku.get(buyPermit, False) status 可买 if (not sold_out and buy_permit) else 不可买 results.append({ perform_id: perform_id, performance: perf_name, sku: sku_name, status: status }) return results很多教程只会让你打印原始JSON但实际监控场景里你会被海量字段淹没。解析的重点是提炼出“状态变化”的信号字段也就是soldOut和buyPermit这两个布尔值。状态一旦从False/False组合变成可买就说明出票了。3.4 定时轮询与状态变化检测轮询的逻辑不复杂每N秒请求一次接口比对状态快照发生变化就触发通知。为了避免重复通知我维护一个last_status字典只有当状态和上次不一致时才推送。import time def monitor(item_id, interval10, notify_funcNone): last_status {} while True: try: data fetch_item_info(item_id) perf_list parse_performances(data) current_status {} for item in perf_list: key f{item[performance]}-{item[sku]} current_status[key] item[status] # 对比状态变化 for key, status in current_status.items(): if key not in last_status: last_status[key] status continue if last_status[key] ! status: if status 可买 and notify_func: notify_func(f【余票监控】{key} 状态变为{status}) last_status[key] status # 输出当前概览方便调试 print(datetime.now().strftime(%Y-%m-%d %H:%M:%S), current_status) except Exception as e: print(请求异常, e) time.sleep(interval) if __name__ __main__: monitor(item_id745341228510, interval10)这个示例足够跑通流程。间隔时间建议设8到15秒太频繁容易被限流太慢则失去实时性。实测下来开票前5分钟把间隔设为3秒左右开票后恢复正常频率效果最好。3.5 推送通知用PushPlus把消息发到微信通知是本项目的灵魂。我的做法是用PushPlus的免费通道。def send_pushplus_notification(content): token 你的token url http://www.pushplus.plus/send payload { token: token, title: 大麦网余票提醒, content: content, template: txt } resp requests.post(url, jsonpayload) return resp.json()把这个函数作为monitor的notify_func参数传入即可。你也可以在开票前30分钟发一条“即将开售”的提醒别自己傻等。实际操作中我更建议把“开售前提醒”和“开售中余票状态变化提醒”分开配置因为抢票用户在开售前需要的是提前进入页面等待而开售后需要的是第一时间知道哪个票档有票。这两个场景的监控频率和信息侧重点不一样。4. 实测中踩过的坑接口字段变化与反爬策略这个项目的“坑”比功能本身更值得聊。我第一次跑通的时候第二天再跑脚本直接报错——不是代码问题而是服务端返回的数据结构变了。最典型的是两个问题。第一个坑字段层级不固定。大麦网详情接口在App端和H5端返回的JSON结构不同而且会时不时调整字段名。比如有的版本里票档叫skuList有的版本里叫performBasessoldOut字段有时不在票档里而在场次层。所以写解析代码时必须做防御性处理用data.get()而不是data[xxx]每个层级都设默认值否则一个KeyError就会让监控中断。第二个坑请求频率过高会触发风控。我刚开始测试时把间隔设成1秒跑了十分钟左右接口返回了异常数据所有票档都变成“不可买”后来才发现是IP被临时限制了。所以轮询间隔真的别太激进。另外Cookie会过期特别是这种涉及登录态的接口基本上每隔几天就要重新抓一次。建议在代码里把Cookie放到单独配置文件里方便更新而不是写死在代码中。还有一个容易被忽略的问题时区。大麦网详情接口里返回的开票时间通常是时间戳格式startTime单位是毫秒。如果你直接把时间戳打印出来看会以为时间对不上其实是没做时区转换。写个转换函数from datetime import datetime, timezone, timedelta def ts_to_str(ts_ms): ts ts_ms / 1000 dt datetime.fromtimestamp(ts, tztimezone(timedelta(hours8))) return dt.strftime(%Y-%m-%d %H:%M:%S)实测下来最让人痛苦的还不是技术而是反馈延迟。你以为收到通知的时候票刚放出来实际上从接口轮询到通知推送再到你打开App已经过去二三十秒了。热门演出在这个窗口内就可能被抢完。所以我不建议把它当“保证能抢到票”的方案它更像是一个“防止你完全错过开票”的方案。真正想抢热门场次还是得靠平台自己的预约功能在开售前手动进入页面配合这个监控做兜底。5. 关于速度的误解网速、手速、脚本到底赢在哪里聊点扎心的。不少人对“抢票脚本”的理解是“脚本比你手快所以能赢”但在我实测下来脚本在“查询”环节赢你在“下单”环节并不比真人快多少。因为下单环节的核心瓶颈是库存锁定的成功率和风控校验是否通过。而这两个因素跟“手速”关系不大跟账号状态、设备环境、网络出口的稳定性关系更大。所以真正合理的自动化策略是**“人机协同”**开售前监控脚本定时获取开票剩余时间提前3分钟通知你让你打开App候着。开售瞬间提醒脚本高频轮询探测到购买入口开放或余票状态变化第一时间推送。人工抢票收到通知后你亲自下单选择观演人、确认订单。这个流程里脚本帮你解决的是“信息差”问题而不是“速度”问题。为什么强调这一点因为很多人把希望寄托在一个全自动脚本上结果账号被风控、订单没锁上反而比人工更惨。我见过最可惜的情况是一个朋友写的自动下单脚本跑通了但因为下单时没有正确选择观演人订单创建后又在待支付页面超时最后什么也没买到。这种脚本层面的“成功”和买到票之间隔着很多业务细节。另外说一个经常被忽略的技术细节在大麦网App端抢票比网页端优先级更高因为很多热门场次的票额只在App端释放网页端显示“无票”不代表真无票。如果只用网页端接口做监控可能会出现“监控说没票但App里明明能买”的情况。所以监控代码里的接口和字段最好以App端抓包结果为准。用手机抓包工具比如Stream或Charles配合代理能抓到App端的mtop接口解析方式和H5端类似只是请求头里多了App标记。我在实际开发中还试过用WebSocket做实时监听研究了大麦网是否推送库存变更事件后来发现普通用户页面没有这种能力所以还是老老实实用轮询。轮询方案的缺点是存在无法消除的延迟窗口但它胜在简单、稳定、可解释这也是我最终保留轮询方案的原因。后台跑这个监控脚本时建议用screen或nohup让它在服务器上常驻而不是一直开着电脑终端。云服务器选最低配就行脚本占用的内存很小主要开销在网络请求上。要注意如果你用的是家庭宽带的IP长期高频轮询反而容易触发运营商层面的限制所以我最后是把间隔稳定在10秒整晚跑一两个演出监控完全没问题。写到这里我觉得有必要再重复一遍边界这个脚本的价值是让你以合规的方式把“盯梢”这件事自动化它不帮你下单、不绕过验证码、不破坏平台规则。我把它分享出来是希望每个想研究的人都能理解接口监控的通用思路任何网页上的动态数据都可以通过“抓包→模拟请求→解析关键字段→定时对比→触发通知”这套流程来实时追踪。用这套思路你可以监控商品降价、监控车牌号释放、监控课程放票逻辑完全一样只换接口和字段就行。最后再分享一个小技巧把异常捕获做得再细一点不要用一整个except Exception包住所有逻辑。我会分别捕获网络请求异常、JSON解析异常和字段缺失异常针对网络异常做指数退避重试针对解析异常打印出原始响应的前500个字符方便快速定位是接口改了还是Cookie过期了。这几个小函数看起来不起眼但正是它们决定了一个监控脚本能不能稳定跑一周不挂。本文还有配套的精品资源点击获取
