ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

拆解大麦网抢票脚本:Selenium自动化实战与避坑指南

拆解大麦网抢票脚本:Selenium自动化实战与避坑指南 简介这个资源包是大麦网演唱会抢票脚本的完整实现基于Python与Selenium框架适合有一定编程基础、希望实现演唱会门票自动化抢购的读者使用。脚本核心由主程序、配置文件和文档组成全部6个文件里包含.py主逻辑、.json参数配置、.yml定时任务工作流、.md使用说明以及示例图片压缩包仅43KB便于快速部署。目前已有810人学习下载说明其在自动化购票和网页登录模拟方面有实际参考价值。脚本内置Cookie初始化与持久化机制首次启动会唤起浏览器完成登录支持扫码、短信和密码等多种方式同时附有环境依赖说明与版本匹配提示读者可结合自身需求调整购票人信息或执行时机。对于研究Selenium登录态管理、表单自动提交和定时触发的开发者这套代码也提供了不错的实战范例。1. 有人把 Selenium 抢票写成了 zip我先拆了再说抢票脚本这种东西很多人第一反应是灰产。但我拆开这个大麦网演唱会抢票脚本.zip 以后发现它就是一套用 Selenium 把浏览器操作自动化的小项目damai_ticket.py 负责打开大麦网页版登录后把 Cookie 存成 cookies.pkl开抢时自动选场次、选票档、填实名购票人最后停在提交订单页。脚本解决的痛点是演出票的“开始抢购”时间一到靠人手要在两秒内完成选场次、勾选票价、选择购票人三个动作几乎不可能脚本只是把这些点击压缩成自动化顺序。适合你的是至少能读懂 Python 的开发者而不是完全不懂编程的小白因为你需要自己改 config.json 里的演出 ID 和购票人信息。2. damai_ticket.py 的运行链路从 zip 到 Selenium 实例解压 zip 第一眼我的反应是东西比 README 还少。目录里真正的核心就是 damai_ticket.py配合 config.json、cookies.pkl运行时生成和 .github/workflows。没有逆接口没有加签名算法整个思路是完整模拟一个真人坐在 Chrome 前操作。这个选择很关键它意味着大麦页面改版你只需要改元素定位如果走抓包方案每次接口加一个加密字段维护成本就高得多。文件/目录作用damai_ticket.py主流程登录、Cookie 存取、开抢、选票、提交订单config.json目标场次、票价档位、购票人、开抢时间等参数README.md运行说明、环境准备和注意事项.github/workflows预留的 CI 配置实际本地跑更靠谱cookies.pkl运行时生成的登录态序列化文件damai_ticket.py 的可执行路径分成两条检测到 cookies.pkl 就直接加载登录态没有则打开登录页等人工登录登录成功后把 Cookie 序列化到文件。下面这段是我在复现时抽出来的 driver 初始化逻辑基本和原项目一致from selenium import webdriver from selenium.webdriver.chrome.options import Options def create_driver(): options Options() # 去掉自动化提示条避免前端检测到 navigator.webdriver 特征 options.add_experimental_option(excludeSwitches, [enable-automation]) # 桌面宽度下按钮不会折叠进弹层点击更稳定 options.add_argument(--start-maximized) return webdriver.Chrome(optionsoptions)这里有两个容易被忽略的参数。excludeSwitches 会把 Chrome 顶部的“Chrome 正受到自动测试软件控制”提示条去掉这是社区里最常见的防自动化特征做法--start-maximized 则是为了让按钮直接落在可点击区域很多抢票按钮在移动端视口下会被折叠进弹层桌面宽度下反而稳定。Cookie 处理是这套脚本的生命线。初次运行没有 cookies.pkl所以流程是先打开登录页等人扫一扫登录成功后用 pickle 把当前会话的 Cookie 存下来。第二次起就直接加载不再走扫码。import os import pickle COOKIE_FILE cookies.pkl def ensure_cookie(driver): if not os.path.exists(COOKIE_FILE): driver.get(https://passport.damai.cn) # 阻塞等待人工扫码或账号登录完成 input(登录完成后按回车继续...) with open(COOKIE_FILE, wb) as fp: pickle.dump(driver.get_cookies(), fp) else: driver.get(https://passport.damai.cn) with open(COOKIE_FILE, rb) as fp: for cookie in pickle.load(fp): driver.add_cookie(cookie) driver.get(https://www.damai.cn)add_cookie 必须在当前域名下才能写入所以我会先 driver.get(https://passport.damai.cn)再逐条加 Cookie最后跳回大麦首页。如果你直接 driver.get(https://detail.damai.cn/xxx) 后加 Cookie大概率报 invalid cookie domain。这个坑在 README 里没有写清楚源码里确实存在。另外Cookie 过期后不会自动刷新运行时遇到需要重新登录直接删除 cookies.pkl。3. config.json开抢前先改对这几组参数config.json 是整个脚本唯一需要手动维护的文件。它的参数不算多但每一个都直接影响抢票结果我把核心字段拆出来逐个说。{ target_url: https://detail.damai.cn/item.htm?id替换为真实演出ID, session: 2025-07-01 19:30, price_index: 1, ticket_num: 2, buyer_ids: [张三], start_time: 2025-06-20 12:00:00, retry_interval: 0.5 }字段含义常见错误target_url演出详情页地址直接复制购物车页脚本定位不到“立即购买”session想要抢购的场次时间填了已下架场次页面不会出现对应按钮price_index票价档位索引从 1 开始档位数量变化后越界点错档位ticket_num购票张数超过限购数量提交订单时被驳回buyer_ids购票人实名证件名填了未实名认证的人页面没有勾选项start_time本地机器上的开抢时刻本机时间不准比平台晚起跑retry_interval失败后重试间隔秒数低于 0.3 秒会频繁刷新触发滑块buyer_ids 不是随便填名字登录账号必须先完成实名制认证并且至少添加一位购票人实名信息。脚本做的只是把订单页里已有的人选自动勾选没法凭空创建一个实名购票人。很多票务活动每个订单限制 2 张所以这个字段数量也别超过限购人数否则最后一步校验会被打回。接下来是时间起点。start_time 是拿本机系统时间做倒计时不是从服务器拉时间。这就意味着抢票前必须保证电脑时间与真实时间误差小于 1 秒。我的做法是用下面这条命令强制同步系统时间# Windows 下强制同步本机时间 w32tm /resync /force如果你在 macOS 或 Linux 上跑可以用 sntp 或 chronyd 校时但核心思路一样脚本对本地系统时钟的依赖比想象中大。下面这段是开抢前的轮询逻辑它能等到毫秒级条件满足后才打开目标页import time from datetime import datetime while datetime.now().strftime(%Y-%m-%d %H:%M:%S) config[start_time]: time.sleep(0.1) for attempt in range(30): driver.get(config[target_url]) try: buy_btn WebDriverWait(driver, 3).until( EC.element_to_be_clickable((By.XPATH, //span[text()立即购买])) ) buy_btn.click() break except Exception: time.sleep(config[retry_interval])retry_interval 是每次尝试失败后的暂停秒数不要低于 0.3否则等于把页面请求刷到手抖反而可能被要求滑块验证。WebDriverWait(driver, 3) 表示当前加载周期最多等 3 秒如果到时间按钮还没渲染就进入下一次刷新。这种实现比固定 time.sleep(0.1) 抢跑更稳因为每次刷新的是整页 DOM轮询的是按钮出现条件而不是固定等待时间。4. Selenium 4.10 边界与订单页异常处理真正让这套脚本“跑不起来”的原因大部分都集中在 Selenium 版本和 ChromeDriver 匹配上。摘要里特意写了 Selenium 4.10.0 以下不是拍脑袋。4.10 之后的 Selenium Manager 开始接管 ChromeDriver 下载但它默认找的 driver 版本经常和新版 Chrome 不一致而且国内网络环境容易卡在下载阶段。所以我建议直接锁版本pip install selenium4.0,4.10然后做版本匹配检查。用命令行分别确认 Chrome 和 ChromeDriver 的主版本号chrome --version chromedriver --version两个版本号主版本必须一致比如 Chrome 114 配 ChromeDriver 114.x。如果配错Selenium 4.10 以下会报 session not created: This version of ChromeDriver only supports Chrome version 113这个提示已经算友好。更隐蔽的是 Chrome 自动升级后driver 还是旧的你需要重新下载对应版本的 ChromeDriver 并覆盖到 PATH 里的原文件。进入详情页之后还有几个常见异常值得记住异常触发场景处理办法ElementClickInterceptedException弹层或底部悬浮条遮挡按钮显式等待弹层关闭或 JS 兜底点击TimeoutException页面刷新过慢按钮 3 秒内未出现调大 WebDriverWait 超时检查 target_urlInvalidCookieDomainException未在目标域名下 add_cookie先 get 到同域名页面再加载 CookieSessionNotCreatedExceptionChrome 与 ChromeDriver 版本不匹配换成同主版本的 driver到了订单确认页还有一个更隐蔽的坑弹层遮罩。大麦的座位图和温馨提示弹层会盖住“提交订单”按钮Selenium 的 element.click() 会抛 ElementClickInterceptedException。比较稳的写法是显式等待 最后执行 JS 兜底def click_after_ready(driver, xpath, timeout5): element WebDriverWait(driver, timeout).until( EC.element_to_be_clickable((By.XPATH, xpath)) ) try: element.click() except Exception: # 弹层遮挡时直接用 JS 点击目标元素 driver.execute_script(arguments[0].click();, element) click_after_ready(driver, //span[text()提交订单])element_to_be_clickable 会等待元素可见且可点比 visibility_of_element_located 多检查一层 disabled 状态。JS 点击绕过了元素是否被遮挡的校验所以只建议作为最后兜底不要每个按钮都这样点否则页面上的风险控制脚本很容易识别出“非人类操作”。至于并发我不建议做成多线程或多开浏览器。真人操作速度就是脚本的天然节奏同时开 5 个 Chrome 实例的结果不是更快而是更容易被判定为异常请求最后连登录态一起封。这套 zip 的定位是个人自用而不是分布式刷票。5. 复现后我改掉的几个小问题复现完成后我把 README 里没写透的几个关键点补在了自己的启动脚本里。第一件事是删除 cookies.pkl带着全新缓存跑一次。正常表现是 Chrome 自动打开大麦登录页等扫码后脚本把 Cookie 写进新的 pkl第二次运行则直接进入详情页。如果你删掉 pkl 后仍然没有唤起浏览器说明 driver 启动参数里带了 user-data-dir把 Chrome 用户目录里的登录态带出来了。这时候不要只删 pkl还要把 --user-data-dir 参数去掉。第二件事是用一个“已开抢但还有余票”的场次做演练。把 target_url 指向这种场次脚本会在进入页面后直接显示“立即购买”你就能验证选票价档、勾选购票人、跳到订单确认页这一段完整链路。注意看到订单确认页就手动停不要点支付。这个演练能提前暴露两个问题buyer_ids 里填写的实名信息和当前账号不匹配以及 price_index 索引超过实际票价档位数。两个问题都是静默失败只在最后下单才会弹提示日常测试不容易发现。第三件事是重试间隔。我把原配置里的 retry_interval 从 0.3 改到了 0.5因为原来的重试太快在同一个页面上重复触发会导致“操作频繁”。每一轮 driver.get() 其实都会重新加载整套页面资源0.3 秒的间隔大部分时间是在等资源加载不是真的在帮你抢。改到 0.5 后整体点击成功率反而更高而且不容易在开抢前 10 秒就把请求打满。最后还有一个脚本健壮性检查在拉起 Chrome 之前先对 config.json 做一次字段校验检查 buyer_ids 是否为空、start_time 是否晚于当前时间、price_index 是否在票价档位范围内校验通过才启动 driver。我把这套校验写进了 damai_ticket.py 的入口位置避免开抢那一刻才发现参数拼错。本文还有配套的精品资源点击获取
返回列表