某麦网手机端自动抢票脚本

当你目不转睛地盯着屏幕,手指飞速操作着一个自动刷新抢票脚本时,整个过程就像是在编织一张巧妙的网。

首先是 get_cookie 方法,它打开大麦网官网,引导你登录并保存登录后的 cookies。这些小小的数据,就像是一把钥匙,为你打开了自动登录的大门。

接着是 set_cookie 方法,它载入之前保存的 cookies,实现了自动登录的功能。这一步就像是把钥匙插入锁孔,轻松地打开了登录的大门。

然后是 login 方法,它访问目标购票页面并设置 cookie。这就好比是你站在门口,准备进入演出的会场。

接下来是 enter_concert 方法,根据提供的配置和参数,打开浏览器,进入大麦网并登录。如果 cookies 不存在,则获取并保存。这一步就像是你在会场内寻找自己的座位,准备享受演出。

再接着是 choose_ticket 方法,它自动化选票过程,包括选择日期、场次、票价等,并尝试点击购买。这就好比是你在舞台前选择最理想的位置,准备迎接精彩的演出。

接下来是 check_order 方法,在选票后确认订单,选择观影人,并尝试提交订单。这一步就好比是你在购票后核对订单信息,准备享受观影的乐趣。

最后是 click_util 方法,它是一个辅助方法,用于重试点击直到达到预期的页面变化。这就好比是你在购票过程中,不断尝试直到成功抢到心仪的门票。

整个执行流程如同一场精彩的演出,每一个方法都扮演着重要的角色,最终带来了抢票的成功和满足。

这个脚本的功能和特性非常强大,支持配置多个参数,使用 Selenium 模拟用户操作,利用 cookies 实现快速登录,同时自动化处理选票过程中的各种情况,确保了抢票的灵活性、成功率和便利性。

全代码如下:

main.py 文件

# coding: utf-8
from json import loads
from time import sleep, time
from pickle import dump, load
from os.path import exists
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities


class Concert(object):
    def __init__(self, config):
        self.config = config
        self.status = 0
        self.time_start = 0
        self.time_end = 0
        self.num = 0
        self.driver = None

    # 其他方法保持不变...

    def choose_ticket(self):
        print(u"###进入抢票界面###")
        while self.driver.title.find('订单确认') == -1:
            self.num += 1

            if con.driver.current_url.find("buy.damai.cn") != -1:
                break

            try:
                WebDriverWait(self.driver, 3, 0.1).until(
                    EC.presence_of_element_located((By.ID, 'app')))
            except:
                raise Exception(u"***Error: 页面刷新出错***")

            # 处理实名身份遮罩
            try:
                WebDriverWait(self.driver, 3, 0.1).until(
                    EC.presence_of_element_located((By.CLASS_NAME, 'realname-popup')))
                self.driver.find_element(By.CLASS_NAME, 'operate').find_element(By.CLASS_NAME, 'button').click()
            except:
                pass

            buy_button = self.driver.find_element(By.CLASS_NAME, 'buy__button')
            buy_button_text = buy_button.text

            if "即将开抢" in buy_button_text:
                self.status = 2
                raise Exception(u"---尚未开售,刷新等待---")
            elif "缺货" in buy_button_text:
                raise Exception("---已经缺货了---")

            sleep(0.1)
            buy_button.click()
            WebDriverWait(self.driver, 2, 0.1).until(EC.presence_of_element_located((By.CSS_SELECTOR, '.sku-pop-wrapper')))
            
            # 选择日期、场次和票档
            self.select_date()
            self.select_session()
            self.select_price()

            # 提交订单
            self.submit_order()

    def select_date(self):
        date_box = self.driver.find_element(By.CLASS_NAME, 'bui-dm-sku-calendar')
        date_list = date_box.find_elements(By.CLASS_NAME, 'bui-calendar-day-box')
        for idx, date_elem in enumerate(date_list, 1):
            if idx in self.config['date']:
                date_elem.click()
                sleep(0.05)
                break

    def select_session(self):
        session_box = self.driver.find_element(By.CLASS_NAME, 'sku-times-card')
        session_list = session_box.find_elements(By.CLASS_NAME, 'bui-dm-sku-card-item')
        for idx, session_elem in enumerate(session_list, 1):
            if idx in self.config['session']:
                session_elem.click()
                sleep(0.05)
                break

    def select_price(self):
        price_box = self.driver.find_element(By.CLASS_NAME, 'sku-tickets-card')
        price_list = price_box.find_elements(By.CLASS_NAME, 'bui-dm-sku-card-item')
        for idx, price_elem in enumerate(price_list, 1):
            if idx in self.config['price']:
                price_elem.click()
                sleep(0.1)
                break

    def submit_order(self):
        try:
            WebDriverWait(self.driver, 2, 0.1).until(EC.presence_of_element_located((By.CLASS_NAME, 'plus-enable')))
        except:
            raise Exception(u"***Error: ticket_num_up 位置找不到***")

        plus_button = self.driver.find_element(By.CLASS_NAME, 'plus-enable')
        for _ in range(self.config['ticket_num'] - 1):
            plus_button.click()

        buy_button = self.driver.find_element(By.CLASS_NAME, 'sku-footer-buy-button')
        sleep(1.0)
        buy_button_text = buy_button.text
        if not buy_button_text:
            raise Exception(u"***Error: 提交票档按钮文字获取为空***")

        if buy_button_text in ("立即预订", "立即购买", "确定"):
            buy_button.click()
            self.status = 4
            WebDriverWait(self.driver, 3, 0.1).until(EC.title_contains("确认"))
        else:
            raise Exception(f"未定义按钮:{buy_button_text}")

    # 其他方法保持不变...

if __name__ == '__main__':
    try:
        with open('./config.json', 'r', encoding='utf-8') as f:
            config = loads(f.read())
            con = Concert(config)
            con.enter_concert()  # 进入到具体抢购页面
    except Exception as e:
        print(e)
        exit(1)

    while True:
        try:
            con.choose_ticket()
            con.check_order()
        except Exception as e:
            con.driver.get(con.config['target_url'])
            print(e)
            continue

        if con.status == 6:
            print(u"###经过%d轮奋斗,共耗时%.1f秒,抢票成功!请确认订单信息###" %
                  (con.num, round(con.time_end-con.time_start, 3)))
            break

config.json文件:

{
    "date": [14],  // 日期序号
    "sess": [1, 2],  // 场次序号,优先选中的场次序号放在前
    "price": [1, 2, 3, 4, 5, 6],  // 票档序号,优先选中的票档序号放在前
    "real_name": [1],  // 实名者序号(已弃用)
    "nick_name": "",  // 用户昵称(已弃用)
    "ticket_num": 1,  // 购买票数
    "viewer_person": [2],  // 观影人序号,优先选中的序号放在前
    "driver_path": "C:\\Users\\damaihelper\\chromedriver.exe",  // 驱动地址
    "damai_url": "https://www.damai.cn/",  // 大麦首页地址,用于登录
    "target_url": "https://m.damai.cn/damai/detail/item.html?itemId=714001339730",  // 购票的实际地址,需要使用手机端的地址,域名以 https://m.damai.cn/ 开头
    "comment": {
        "title": "comment 下的所有内容为自定义注释,无实际含义",
        "date": "1",
        "sess": "场次序号,优先选中的场次序号放在前,填写的场次序号若大于实际场次序号,则会选中实际场次序号最大的",
        "price": "票档序号,优先选中的票档序号放在前,填写的票档序号若大于实际票档序号,则会选中实际票档序号最大的",
        "real_name": "实名者序号(已弃用)",
        "nick_name": "用户昵称(已弃用)",
        "ticket_num": "购买票数,购买票数与观影人序号的数量务必一致",
        "viewer_person": "观影人序号(预先添加实名观影人),优先选中的序号放在前,填写的序号若大于实际序号,则会放弃选中",
        "driver_path": "驱动地址",
        "damai_url": "大麦首页地址,用于登录",
        "target_url": "购票的实际地址,需要使用手机端的地址,域名以 https://m.damai.cn/ 开头",
        "queue": {
            "title": "列入待抢的链接地址",
            "zhoujielun_0403": "https://m.damai.cn/damai/detail/item.html?itemId=717235298514"
        }
    }
}
© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容