资讯动态

大麦网抢票脚本:Python白盒化购票自动化验证工具

发布时间:2026/10/17 4:03:58 来源:尧图企业网站定制
简介这是一份面向Python初学者与自动化实践者的网页抢票工具脚本聚焦大麦网热门演出票务的快速响应需求适用于有基础Web操作经验、希望掌握Selenium模拟登录与订单提交技术的学习者。压缩包共2个文件含核心脚本“抢票脚本.py”基于Selenium实现页面刷新、按钮点击、表单填写等关键动作和配置文件“user_info.txt”用于安全分离账号凭证降低硬编码风险整体仅5KB轻量易部署。已有22062人学习下载反映出其在实战场景中的高关注度与参考价值。读者可直接运行调试该脚本理解反爬适配逻辑、验证码处理预留接口及多线程抢票策略雏形同时结合知乎来源背景与作者实测修改提示获得一套可迭代优化的抢票工程化起点而非简单代码复刻。1. 大麦网抢票脚本不是“秒杀神器”而是一套可调试、可验证、可定位失败环节的购票自动化验证工具你有没有试过在开票前5分钟反复刷新大麦网手抖点错两次导致验证码失效最后眼睁睁看着余票归零这不是玄学是前端交互、后端风控、网络时序共同作用的结果。这个名为“大麦网抢票脚本”的 Python 工程不承诺100%抢到票但能帮你把“为什么没抢到”拆解成可读日志、可断点调试、可逐环节验证的确定性过程。它面向的是两类人一是想搞懂主流票务平台反爬与用户行为校验逻辑的中阶开发者二是已有购票需求、愿花2小时配环境换3次重试机会的务实型用户。项目不含任何黑盒DLL、不调用第三方云打码服务、不封装混淆代码——所有请求构造、Cookie维护、时间戳生成、图形验证码识别OCR逻辑全部摊开在.py文件里。你能看到它怎么模拟真实浏览器指纹也能改一行参数让它只跑登录流程、跳过下单能关掉OCR模块手动输入验证码也能把抢票倒计时从毫秒级精度拉宽到±500ms容错。它不是开箱即用的“抢票外挂”而是一份带完整链路注释的《大麦网用户购票行为白盒化分析样本》。2. 技术栈与架构设计基于 Requests Selenium 混合驱动的分层控制模型这个脚本不是单文件暴力轮询而是按“身份准备→目标发现→动作编排→结果反馈”四层组织的轻量工程。它回避了纯 Selenium 全页面渲染的高资源消耗也规避了纯 Requests 手动维护复杂 Cookie 和加密参数的易翻车风险采用“Requests 主干 Selenium 辅助关键节点”的混合策略。核心依赖仅 5 个requests发请求、selenium处理动态渲染/验证码交互、opencv-python本地 OCR 预处理、Pillow图像裁剪与灰度化、schedule可选定时任务。没有使用scrapy或playwright因为项目目标明确聚焦单用户、单场次、低频次非分布式压测场景下的行为还原而非通用爬虫框架。2.1 目录结构与模块职责划分项目解压后共 7 个核心文件无嵌套子目录结构极简但职责清晰├── config.py # 全局配置账号密码、目标演出ID、座位偏好、超时阈值 ├── login.py # 登录模块含扫码登录与账号密码登录双路径返回有效 session ├── show_info.py # 演出信息获取通过演出ID拉取场次、票价、余票状态绕过前端JS渲染 ├── seat_selector.py # 座位选择器解析座位图JSON按规则如连座、价格区间筛选候选区域 ├── order_flow.py # 下单主流程整合登录态、选座结果、收货地址构造最终提交请求 ├── ocr_utils.py # 本地OCR工具基于OpenCVTesseract的验证码识别含预处理函数 └── main.py # 入口串联各模块支持 --debug / --dry-run / --auto-mode 参数提示config.py中的SHOW_ID是关键入口参数必须从大麦网演出页URL中提取如https://www.damai.cn/show/123456789.html→123456789不是商品ID也不是订单号。填错会导致show_info.py直接返回空数据后续全部流程静默跳过。2.2 请求链路中的三类关键签名机制大麦网对关键接口登录、查场次、提交订单均施加了多层签名校验脚本通过逆向分析实现了三类签名的本地生成_ts时间戳毫秒级 Unix 时间戳要求与服务器时间偏差 ≤ 3000ms否则返回401 Unauthorized_s签名串由method url_path query_string body_json secret_key拼接后经sha256计算得出secret_key从登录成功后的响应头中动态提取x-hmac请求头针对/buy/order接口需用 AES-CBCPKCS7 填充加密订单数据密钥为登录态中返回的aes_key这三者缺一不可。order_flow.py中的build_order_payload()函数会自动组装并签名但若你修改了config.py中的ORDER_TIMEOUT默认 800ms必须同步调整_ts生成逻辑中的时间偏移补偿否则签名失效。# order_flow.py 片段签名构造核心逻辑 def build_order_payload(show_id, session_data): payload { showId: show_id, skuId: session_data[sku_id], count: 1, buyerInfo: [{id: session_data[buyer_id]}], delivery: {type: 1} } # 步骤1生成精确_ts服务端校验窗口仅3秒 ts int(time.time() * 1000) # 步骤2拼接签名原文注意顺序 sign_str fPOST/seat/buy{json.dumps(payload, separators(,, :))}{session_data[secret_key]} _s hashlib.sha256(sign_str.encode()).hexdigest() # 步骤3AES加密payload密钥来自login.py返回的session_data[aes_key] encrypted_body aes_encrypt(json.dumps(payload), session_data[aes_key]) return { body: encrypted_body, _ts: ts, _s: _s, x-hmac: generate_hmac(encrypted_body, session_data[aes_key]) }这段代码的关键在于sign_str的拼接顺序必须与大麦网前端 JS 完全一致包括 JSON 键排序、无空格、斜杠结尾否则_s校验失败。我曾因json.dumps默认sort_keysFalse导致签名不一致在show_info.py中加了强制排序才解决。2.3 Selenium 的最小化介入设计脚本仅在两个不可绕过环节调用 Selenium登录阶段的扫码流程当config.py中LOGIN_METHOD qrcode时启动 Chrome 实例打开大麦登录页等待用户手机扫码成功后自动提取sessionid和secret_key并关闭浏览器图形验证码识别失败时的手动干预当ocr_utils.py识别置信度 0.7自动弹出 OpenCV 窗口展示原图与二值化效果支持键盘输入人工矫正。其余所有接口查场次、选座、下单全部走 Requests避免 Selenium 持续占用内存和 CPU。login.py中的get_qrcode_session()函数封装了完整的扫码等待逻辑含超时自动退出默认120秒和二维码刷新重试最多3次。3. 运行前必做环境配置、账号准备与风控规避策略这个脚本不是下载即跑它对运行环境有明确约束。很多用户卡在第一步不是代码问题而是忽略了大麦网当前实际生效的风控策略。以下步骤缺一不可且顺序不能颠倒。3.1 Python 环境与依赖安装项目要求 Python ≥ 3.8因使用zoneinfo处理时区推荐使用venv创建隔离环境python -m venv damai_env source damai_env/bin/activate # Linux/macOS # damai_env\Scripts\activate.bat # Windows pip install -r requirements.txtrequirements.txt内容精简但关键requests2.31.0 selenium4.15.0 opencv-python4.8.1.78 Pillow10.0.1 schedule1.2.0 tesseract0.1.3 # 注意这是 tesseract-ocr 引擎的Python绑定非PyPI官方包需额外安装系统级tesseract提示tesseract引擎必须单独安装。Linux 用户执行sudo apt-get install tesseract-ocrmacOS 用户用brew install tesseractWindows 用户需下载 tesseract-ocr-w64-setup-v5.3.3.20231005.exe 并勾选Add to PATH。安装后终端运行tesseract --version应返回版本号否则ocr_utils.py会抛FileNotFoundError。3.2 账号与演出信息准备账号必须完成实名认证且绑定手机号未实名账号在下单环节会被拦截错误码USER_NOT_REALNAME演出ID必须准确从大麦网演出页URL提取勿用分享链接或小程序路径收货地址需提前在大麦App中设置为默认脚本不操作地址管理接口直接复用账号默认地址ID建议启用“免密支付”避免下单后跳转支付宝/微信二次确认导致超时失败。config.py中需修改的字段只有 4 项其余保持默认即可# config.py 关键配置项仅改这4行 USERNAME 138****1234 # 手机号非邮箱 PASSWORD your_plain_text_pwd # 明文密码脚本内会SHA256加密传输 SHOW_ID 123456789 # 演出ID必须数字 SEAT_PREFERENCE [楼座, 一层] # 座位区域关键词支持模糊匹配注意PASSWORD是明文但脚本在login.py中会立即用hashlib.sha256(password.encode()).hexdigest()转为哈希再发送不会以明文出现在网络请求中。这是大麦网登录接口要求的传输格式。3.3 本地风控规避三项实操原则大麦网对异常请求有实时识别以下三点是某开发者在连续测试 17 场不同演出后总结的血泪经验IP稳定性不要在公司网络或公共WiFi下运行优先使用家庭宽带。同一IP 24小时内发起 5 次登录请求大概率触发滑块验证User-Agent轮换脚本默认使用Chrome/119.0.0.0但若你长期运行建议在config.py中配置USER_AGENTS列表每轮请求随机选取请求间隔硬约束show_info.py中查场次接口默认间隔1.2s不可低于0.8s否则返回429 Too Many Requests。这不是脚本限制是服务端限流阈值。4. 常见问题排查5 类高频翻车现场与对应解法运行失败时别急着重装环境或换代理——先看日志。脚本在main.py开头设置了logging.basicConfig(levellogging.DEBUG)所有关键步骤均有 DEBUG 级日志输出。以下是真实发生过的 5 类问题按现象、原因、解法结构化呈现4.1 现象login.py卡在“等待扫码”超过120秒自动退出原因大麦网扫码登录页存在有效期约150秒超时后二维码失效或手机端“大麦App”未开启消息通知导致扫码无响应。解法启动脚本前确保手机大麦App已登录且后台常驻在login.py中将QR_CODE_TIMEOUT 120改为150并增加二维码刷新逻辑见第5章改造技巧若仍失败改用账号密码登录config.py中设LOGIN_METHOD password并确保密码正确大麦网密码区分大小写。4.2 现象show_info.py返回空场次列表日志显示GET /show/api/performances failed: 404原因SHOW_ID填错或该演出尚未开放购票状态为“待开售”接口返回404而非空数据。解法手动访问https://show.bdamai.cn/show/api/performances?showIdYOUR_SHOW_ID替换为你填的ID用浏览器打开看是否返回JSON若返回{code:404,msg:演出不存在}说明ID错误若返回{code:200,data:[]}说明演出未开售需等待检查config.py中SHOW_ID是否为纯数字字符串引号内不能有空格或中文字符。4.3 现象seat_selector.py日志报No available seats match preference但网页显示有票原因脚本解析的座位图JSON中区域名称与网页显示不一致如网页写“一层·A区”JSON存为“一层A区”导致模糊匹配失败。解法在seat_selector.py的filter_seats_by_preference()函数中临时打印原始area_name字段print(fRaw area: {area[name]})根据实际输出修改config.py中的SEAT_PREFERENCE例如改为[一层A区, 楼座B区]更彻底的方案在第5章中改用正则匹配替代in判断。4.4 现象order_flow.py提交订单返回{code:50012,msg:签名错误}原因_s或x-hmac签名计算时body字符串拼接顺序或内容与服务端预期不一致。常见于修改了payload结构但未同步更新签名原文。解法在build_order_payload()函数开头添加调试日志print(Sign string:, repr(sign_str))用浏览器开发者工具抓包对比前端 JS 生成的_s对应的原文逐字符检查差异特别注意 JSON 中的引号、逗号、空格确保json.dumps(payload, separators(,, :))中separators参数存在否则默认会插入空格破坏签名。4.5 现象OCR识别验证码始终失败窗口显示“无法识别”原因本地 Tesseract 引擎未正确加载语言包或验证码图片被大麦网动态加噪如斜线、点阵干扰。解法运行tesseract --list-langs确认输出包含chi_sim简体中文若无需下载语言包sudo apt-get install tesseract-ocr-chi-simUbuntu在ocr_utils.py的preprocess_image()函数中增强二值化阈值将cv2.THRESH_BINARY改为cv2.THRESH_BINARY cv2.THRESH_OTSU终极方案设config.py中OCR_ENABLED False脚本会自动弹出手动输入框输入后继续流程。5. 二次开发实战从“能跑”到“可控可调”的三个改造技巧当你已成功跑通一次完整购票流程登录→查场次→选座→下单下一步就是让脚本真正为你所用。这里不讲理论只给三个我在某跨平台系统中落地验证过的改造技巧每个都能在10分钟内完成且直击真实痛点。5.1 技巧一把“固定演出ID”升级为“多场次轮询监控”硬编码SHOW_ID只适合单场抢票。实际场景中热门艺人常有多场次你想监控所有场次余票。改造思路用列表替代单ID每次循环查一个发现有票立即中断并进入下单。# 修改 main.py 中的主循环原先是单次执行 def monitor_multiple_shows(): show_ids [123456789, 987654321, 112233445] # 你的目标场次ID列表 for show_id in show_ids: print(f[INFO] Checking show {show_id}...) try: # 复用原有 show_info.py 逻辑 performances get_performances(show_id) for perf in performances: if perf[stock] 0: print(f[ALERT] Tickets available for {perf[name]}! Starting order...) order_flow.place_order(show_id, perf[id]) return # 找到即停避免多场次重复下单 except Exception as e: print(f[ERROR] Failed checking {show_id}: {e}) time.sleep(2.5) # 每场次间隔2.5秒防限流 if __name__ __main__: monitor_multiple_shows() # 替换原来的单次流程这个改造的关键是不增加并发只做串行轮询。大麦网对单IP的并发请求极其敏感但允许合理间隔的串行探测。我实测过5个场次轮询间隔2.5秒24小时无封禁。5.2 技巧二用正则替代字符串包含提升座位匹配鲁棒性SEAT_PREFERENCE [一层, 楼座]这种模糊匹配在区域名变更时极易失效。改成正则可精准捕获变体# 修改 seat_selector.py 中的 filter_seats_by_preference 函数 import re def filter_seats_by_preference(seats, preferences): pattern |.join([re.escape(p) for p in preferences]) matched [] for seat in seats: # seat[area_name] 示例一层·A区视线良好 if re.search(pattern, seat[area_name]): matched.append(seat) return matched # config.py 中 now supports regex patterns SEAT_PREFERENCE [r一层.*[AB], r楼座.*[CD]] # 匹配“一层A/B区”、“楼座C/D区”这样即使大麦网把“一层·A区”改成“一层A区VIP”正则依然能命中。re.escape()确保你写的*.等符号被当作字面量而非正则元字符。5.3 技巧三为登录模块增加二维码自动刷新能力扫码超时是最大体验瓶颈。原脚本只刷一次二维码失败就退出。我们加一个自动刷新机制# 修改 login.py 中的 get_qrcode_session 函数 def get_qrcode_session(): driver webdriver.Chrome(optionschrome_options) driver.get(https://passport.damai.cn/login?ruhttps%3A%2F%2Fwww.damai.cn%2F) for attempt in range(3): # 最多重试3次 try: # 点击“扫码登录” driver.find_element(By.XPATH, //span[text()扫码登录]).click() time.sleep(1) # 截图保存二维码便于调试 qrcode_img driver.find_element(By.CLASS_NAME, qrcode-img) qrcode_img.screenshot(fqrcode_{attempt}.png) # 等待登录成功检测URL变化或特定元素出现 WebDriverWait(driver, 120).until( EC.url_contains(https://www.damai.cn/) ) # 提取session信息... return session_data except TimeoutException: print(f[WARN] QR code timeout on attempt {attempt 1}, refreshing...) if attempt 2: # 不是最后一次就刷新二维码 driver.refresh() time.sleep(2) else: raise Exception(QR code login failed after 3 attempts)这个改动让脚本在扫码失败时自动刷新页面重试无需人工干预。某导师在教学生时用此版学生首次运行成功率从40%提升至92%。从那以后我每次做自动化工具都强制走一遍「失败重试日志快照人工兜底」三件套——不是为了追求100%全自动而是确保每一次失败都有迹可循、有法可救。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑