Python 大麦网抢票脚本全解析:从原理到实战(模块化拆解 + 优化指南)

Python 大麦网抢票脚本全解析:从原理到实战(模块化拆解 + 优化指南)

在抢票场景中,手动操作往往难以匹敌抢票工具的响应速度。今天分享一款基于 Python+Selenium 的大麦网抢票脚本,它通过面向对象编程思想,将复杂抢票流程拆分为独立模块,实现了 Cookie 免登录、自动选座、订单提交等核心功能。本文将从模块设计、核心原理、实战注意事项三个维度,带你吃透这款脚本的每一处细节。

一、脚本核心架构总览

脚本整体采用「面向对象 + 模块化」设计,核心逻辑封装在Concert类中,配合全局配置模块和入口函数,形成 “配置→初始化→登录→抢票→收尾” 的完整流程。

整体结构图谱

大麦网抢票脚本
├── 基础配置模块(库导入+全局常量)
├── 核心类 Concert(抢票主逻辑)
│   ├── Cookie管理模块(免登录核心)
│   ├── 登录模块(登录方式分发+页面初始化)
│   ├── 抢票核心模块(选座+下单)
│   ├── 辅助工具模块(元素判断+资源释放)
└── 入口函数(脚本执行入口)

这种设计的优势在于:单个模块职责单一,便于维护和扩展(比如更换演出、修改登录方式时,仅需调整对应模块)。

二、基础配置模块:脚本运行的 “地基”

基础配置模块负责准备脚本运行所需的依赖库和固定参数,是整个脚本的 “起点”。

1. 依赖库导入及作用

import os  # 文件存在性判断、路径处理
import time  # 延时控制,模拟人工操作节奏
import pickle  # Cookie序列化/反序列化,实现免登录
from time import sleep  # 简化延时调用
from selenium import webdriver  # 浏览器自动化核心工具
from selenium.webdriver.common.by import By  # 元素定位方式枚举

各库的核心作用的:

  • selenium:核心依赖,负责打开浏览器、定位按钮、模拟点击等所有交互操作;
  • pickle:解决 “重复登录” 问题,将登录后的 Cookie 保存到本地,下次运行直接复用;
  • os:判断 Cookie 文件是否存在,实现 “有 Cookie 免登录,无 Cookie 则手动登录” 的逻辑;
  • time/sleep:避免操作过快导致页面未加载完成,平衡 “抢票速度” 和 “操作稳定性”。

2. 全局常量配置

# 大麦网核心页面URL
damai_url = 'https://www.damai.cn/'  # 主页
login_url = 'https://passport.damai.cn/login?ru=https%3A%2F%2Fwww.damai.cn%2F'  # 登录页
target_url = '目标演出详情页'  # 需抢票的演出页面

常量设计的意义:将高频使用的 URL 固化,后续更换演出时,仅需修改target_url,无需改动核心逻辑,降低维护成本。

三、核心类 Concert:抢票逻辑的 “大脑”

Concert类是脚本的核心,所有抢票操作都围绕这个类的方法展开。类内通过属性控制流程状态,通过方法实现具体功能,逻辑清晰且可复用。

1. 类初始化:初始化核心属性

def __init__(self):
    self.status = 0  # 流程状态标记(0=初始化,2=登录成功,3/4/5=不同购票阶段)
    self.login_method = 1  # 登录方式(0=模拟登录,1=Cookie免登录)
    self.driver = webdriver.Chrome(executable_path='chromedriver.exe')  # Chrome驱动对象
  • self.status:相当于 “流程进度条”,通过状态值控制后续操作(比如只有status=2(登录成功),才能执行选座操作);
  • self.login_method:支持两种登录方式切换,Cookie 免登录是核心优化点,避免重复扫码 / 输入账号密码;
  • self.driver:Chrome 浏览器驱动实例,所有浏览器操作(打开页面、点击按钮等)都通过该对象实现。

四、模块拆解:逐一看懂核心功能

模块 1:Cookie 管理模块(免登录核心)

Cookie 是网站记录用户登录状态的关键数据,该模块通过 “保存 Cookie→读取 Cookie” 的流程,实现免登录功能,是抢票效率的核心保障。

1. set_cookies():首次登录并保存 Cookie
def set_cookies(self):
    self.driver.get(damai_url)  # 打开大麦主页
    print('###请点击登录###')
    # 等待用户点击登录按钮(页面标题未变则持续等待)
    while self.driver.title.find('大麦网-全球演出赛事官方购票平台') != -1:
        sleep(1)
    print('###请扫码登录###')
    # 等待用户扫码完成(登录成功后页面标题变化)
    while self.driver.title != '大麦网-全球演出赛事官方购票平台-100%正品、先付先抢、在线选座!':
        sleep(1)
    # 保存Cookie到本地文件
    pickle.dump(self.driver.get_cookies(), open('cookies.pkl', 'wb'))
    print('###cookie保存成功###')
    self.driver.get(target_url)  # 跳转到抢票页

核心逻辑

  • 手动触发登录:脚本不处理验证码 / 扫码,需要用户手动完成登录操作;
  • 状态判断:通过监控页面标题变化,判断登录是否完成(避免代码提前执行);
  • 序列化保存:用pickle.dump()将 Cookie 写入cookies.pkl文件,实现状态持久化。
2. get_cookie():读取 Cookie 实现免登录
def get_cookie(self):
    # 读取本地Cookie文件
    cookies = pickle.load(open('cookies.pkl', 'rb'))
    for cookie in cookies:
        # 构造符合要求的Cookie字典(必须指定domain,否则无效)
        cookie_dict = {
            'domain': '.damai.cn',  # 关键:Cookie绑定的域名
            'name': cookie.get('name'),
            'value': cookie.get('value')
        }
        self.driver.add_cookie(cookie_dict)  # 注入Cookie到浏览器
    print('###载入cookie###')

关键注意点

  • domain: '.damai.cn'是必填项:Cookie 是域名绑定的,不指定域名会导致 Cookie 注入无效,无法免登录;
  • 注入时机:需先打开目标页面(target_url),再注入 Cookie,否则 Cookie 无法生效。

模块 2:登录模块(登录逻辑分发 + 页面初始化)

登录模块负责根据配置的登录方式,完成 “手动登录” 或 “Cookie 免登录”,并初始化抢票页面。

1. login():登录方式分发
def login(self):
    if self.login_method == 0:
        self.driver.get(login_url)  # 直接打开登录页,手动登录
        print('###开始登录###')
    elif self.login_method == 1:
        # 检查Cookie文件是否存在
        if not os.path.exists('cookies.pkl'):
            self.set_cookies()  # 无Cookie则执行首次登录并保存
        else:
            self.driver.get(target_url)  # 有Cookie则直接打开抢票页
            self.get_cookie()  # 注入Cookie免登录

逻辑分支

  • 方式 0(模拟登录):适用于 Cookie 失效或首次使用的场景,需手动输入账号密码 / 扫码;
  • 方式 1(Cookie 免登录):适用于重复抢票场景,直接复用之前的登录状态,节省时间。
2. enter_concert():初始化浏览器 + 登录 + 弹窗处理
def enter_concert(self):
    print('###打开浏览器,进入大麦网###')
    self.login()  # 执行登录
    self.driver.refresh()  # 刷新页面,使Cookie生效
    self.status = 2  # 标记登录成功
    print('###登录成功###')
    # 关闭登录后的弹窗(通过XPATH定位关闭按钮)
    if self.isElementExist('/html/body/div[2]/div[2]/div/div/div[3]/div[2]'):
        self.driver.find_element(By.XPATH, '/html/body/div[2]/div[2]/div/div/div[3]/div[2]').click()

额外处理

  • 页面刷新:注入 Cookie 后必须刷新,否则页面无法识别登录状态;
  • 弹窗处理:登录后可能出现广告弹窗,通过isElementExist()判断并关闭,避免弹窗遮挡后续操作。

模块 3:抢票核心模块(选座 + 下单)

这是脚本的核心业务模块,负责监控购票按钮状态、自动选座、提交订单,全程模拟人工抢票流程。

1. choose_ticket():监控购票按钮并触发对应操作
def choose_ticket(self):
    if self.status == 2:  # 仅登录成功后执行
        print('=' * 30)
        print('###开始进行日期及票价选择###')
        # 未进入订单页面则持续监控
        while self.driver.title.find("确认订单") == -1:
            try:
                buybutton = self.driver.find_element(By.CLASS_NAME, 'buybtn').text
                # 根据按钮文本执行不同操作
                if buybutton == '提交缺货登记':
                    # 无票状态,刷新页面重新监控
                    self.driver.get(target_url)
                elif buybutton == '立即预定':
                    self.driver.find_element(By.CLASS_NAME, 'buybtn').click()
                    self.status = 3
                elif buybutton == '立即购买':
                    self.driver.find_element(By.CLASS_NAME, 'buybtn').click()
                    self.status = 4
                elif buybutton == '选座购买':
                    self.driver.find_element(By.CLASS_NAME, 'buybtn').click()
                    self.status = 5
            except:
                print('###没有跳转到订单结算界面###')
            # 分支处理:选座购买/确认订单
            if self.driver.title == '选座购买':
                self.choice_seats()  # 选座逻辑
            elif self.driver.title == '确认订单':
                # 提交订单逻辑
                while True:
                    if self.isElementExist('//*[@id="container"]/div/div[9]/button'):
                        self.check_order()
                        break

核心逻辑

  • 按钮状态监控:通过循环获取 “购票按钮” 的文本,判断当前票品状态(无票 / 可预定 / 可购买 / 选座购买);
  • 分支跳转:根据不同状态触发对应操作,无票时刷新页面重新监控,有票时进入下一步流程。
2. choice_seats():选座购买逻辑
def choice_seats(self):
    # 停留在选座页面时持续处理
    while self.driver.title == '选座购买':
        # 等待用户选座(提示用户手动选座)
        while self.isElementExist('//*[@id="app"]/div[2]/div[2]/div[1]/div[2]/img'):
            print('请快速选择你想要的座位!!!')
        # 选座完成后点击确认按钮
        while self.isElementExist('//*[@id="app"]/div[2]/div[2]/div[2]/div'):
            self.driver.find_element(By.XPATH, '//*[@id="app"]/div[2]/div[2]/div[2]/button').click()

注意:脚本不支持自动选座(大麦网选座需要人工点击座位区域),此处仅在用户选座后,自动点击 “确认选座” 按钮。

3. check_order():提交订单逻辑
def check_order(self):
    if self.status in [3, 4, 5]:
        print('###开始确认订单###')
        time.sleep(1)  # 等待页面加载
        try:
            # 选中第一个购票人(需提前在大麦网添加购票人信息)
            self.driver.find_element(By.XPATH, '//*[@id="container"]/div/div[2]/div[2]/div[1]/div/label').click()
        except Exception as e:
            print('###购票人信息选中失败, 自行查看元素位置###')
            print(e)
        # 提交订单(延时0.5秒避免点击无效)
        time.sleep(0.5)
        self.driver.find_element(By.XPATH, '//*[@id="container"]/div/div[9]/button').click()
        time.sleep(20)  # 预留支付时间

关键细节

  • 购票人信息:需提前在大麦网绑定购票人(身份证信息),脚本默认选中第一个购票人;
  • 延时控制:点击提交订单前延时 0.5 秒,避免页面未加载完成导致点击无效;
  • 支付预留:最后延时 20 秒,留给用户在浏览器中完成支付操作。

模块 4:辅助工具模块(元素判断 + 资源释放)

该模块提供通用工具方法,支撑核心模块的稳定运行。

1. isElementExist():判断元素是否存在
def isElementExist(self, element):
    flag = True
    try:
        self.driver.find_element(By.XPATH, element)  # 尝试定位元素
        return flag
    except:
        flag = False
        return flag

作用:避免因元素未加载(如按钮、弹窗)导致脚本报错崩溃,是脚本稳定性的重要保障(比如判断弹窗是否存在、提交订单按钮是否加载完成)。

2. finish():脚本收尾
def finish(self):
    self.driver.quit()  # 关闭浏览器,释放资源

作用:抢票完成或出现异常时,关闭浏览器,避免占用系统资源。

五、入口函数:脚本的 “启动开关”

if __name__ == '__main__':
    con = Concert()  # 实例化抢票类
    try:
        con.enter_concert()  # 初始化浏览器+登录
        con.choose_ticket()  # 开始抢票
    except Exception as e:
        print(e)  # 打印异常信息
        con.finish()  # 异常时关闭浏览器

执行流程:实例化Concert类 → 调用enter_concert()完成登录和页面初始化 → 调用choose_ticket()开始抢票 → 捕获异常并关闭浏览器,确保脚本优雅退出。

六、实战注意事项 & 优化建议

1. 实战前准备

  • 安装依赖:执行pip install selenium安装核心库;
  • Chrome 驱动配置:确保chromedriver.exe版本与本地 Chrome 浏览器版本一致(或改用webdriver_manager自动适配);
  • 提前配置:在大麦网添加购票人信息、完成实名认证,避免下单时因信息缺失失败;
  • Cookie 有效期:大麦网 Cookie 有效期有限,若免登录失败,删除cookies.pkl文件后重新运行脚本,手动登录更新 Cookie。

2. 脚本优化方向

  • 显式等待替代固定延时:用WebDriverWait替代sleep(),减少无效等待,提升抢票速度;

    python

    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    # 示例:等待购票按钮加载完成(最多等待10秒)
    WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'buybtn')))
    
  • 多线程抢票:通过多线程同时监控多个演出或座位,提升成功率;
  • 日志记录:添加logging模块,记录抢票流程和异常信息,便于排查问题;
  • 滑动验证处理:若遇到滑动验证,可集成ddddocr等 OCR 库自动识别滑动缺口(需额外开发)。

七、总结

这款大麦网抢票脚本的核心优势在于 “模块化设计” 和 “Cookie 免登录”,将复杂的抢票流程拆分为独立模块,既便于理解和维护,又能灵活扩展功能。脚本本质是 “模拟人工操作”,无法突破大麦网的防爬机制(如验证码、排队机制),但能通过自动化减少人工操作的延迟,提升抢票成功率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值