闲来无事,打开大麦网发现现在大多数演唱票都需要手机端才能抢票,仅有很少一部分支持pc端用网页去抢票,但正所谓:道高一尺,魔高一丈,解决这个反爬问题,我们可以采用Airtest连接仿真机来模拟手机端操作,这次教程我们就先着手去解决利用selenium解决少部分可以用pc端抢票的问题。如果针对手机端抢票的呼声较高,后面我会出一篇关于Airtest抢票的blog。

前提声明:

1、本教程仅用于学习和研究使用,不得用于商业行为。

2、请确保在合法合规的前提前下使用本代码

3、本教程所涉及的操作均为正常模拟用户操作,不涉及任何数据入侵或数据窃取。

一、引言 

在热门演出和赛事门票一票难求的今天,利用自动化工具来提高抢票成功率成为很多人的需求,本文将详细介绍如何使用chromedriver及selenium利用python来编写一个简单的大麦网自动抢票脚本。

二、准备工作

在开始之前,确保开发环境中安装了我们所需要的库:

chromedriver版本: 131.0.6778.87

chrome版本:131.0.6778.140

selenium:4.27.1(用于网页自动化操作)

如果这些并未安装,可以看我之前写的blog,也可以在B站等平台搜索资源进行学习。这里我们就不详细说了。

三、代码分析

1、所需页面URL

首先我们需要定义大麦网首页、登陆页面以及我们想要抢的那张票的页面URL。

damai_url = "https://www.damai.cn/“

login_url = ”https://passport.damai.cn/login?ru=https%3A%2F%2Fwww.damai.cn%2F“

target_url ="https://detail.damai.cn/item.htm?spm=a2oeg.home.card_0.ditem_3.591b23e11Li5yj&id=862317821501“

 我们主要采取面向对象的思想来编写代码,我们首先定义一个类对象,然后进行初始化加载。

class Concert:def __init__(self):self.status = 0 # 状态,表示当前操作执行到哪一步self.login_method = 1 # 0:模拟登录 1:使用cookie登录self.driver = webdriver.Chrome()

然后执行登陆操作,我们需要判断是否需要进行模拟登陆操作,如果需要模拟登录就先打开登陆页面:

    """登录"""def login(self):# 如果为0,模拟登录if self.login_method == 0:self.driver.get(login_url)elif self.login_method == 1:# 如果当前目录下没有这个cookie.pkl文件if not os.path.exists('cookie.pkl'):# 登陆一下记录登录信息self.set_cookies()else:self.driver.get(target_url)# 登陆一下 通过selenium传入一些信息self.get_cookie()

我们来看定义的两个函数:set_cookies()和get_cookie():

    """cookies:登陆网站的时候出现的,记录用户信息"""def set_cookies(self):self.driver.get(login_url)print("###请扫码登陆###")time.sleep(10)print("###登陆成功###")pickle.dump(self.driver.get_cookies(), open('cookie.pkl','wb')) #获取登陆的信息,并保存下来print("###cookie保存成功###")# 登陆成功后就跳转到抢票页面self.driver.get(target_url)# time.sleep(2)# 如果文件中已经有了cookie.pkl文件def get_cookie(self):cookies = pickle.load(open('cookie.pkl','rb'))for cookie in cookies:cookie_dict = {"domain":".damai.cn","name":cookie.get("name"),"value":cookie.get("value"),}self.driver.add_cookie(cookie_dict)print("###载入cookie成功###")

 打开浏览器,状态此时改为1

    def enter_concert(self):print("###打开浏览器,进入大麦网###")# 调用登录self.login()self.driver.refresh()self.status = 1print("###登陆成功###")

购票具体逻辑地实现:如果我们还停留在我们要买的这张票的页面,门票的信息可能是缺货,这个时候需要我们不断的刷新,因此我们可以写一个while循环来实现它,直到点击进入页面:订单确认页为止。给不同的情况,赋予不同的状态,并采用不同的逻辑去判断,比如需要我们手动选座购买的逻辑代码等等。然后就是进入订单确认页的具体逻辑执行,我们可以采取xpath的方式去定位元素。把具体的代码封装到方法中。

    # 抢票并下单:首先判断是否能够购买,如果不能就一直刷新网页,知道能够购买为止def choose_ticket(self):if self.status == 1:print("="*30)print("###请选择日期以及票价###")while self.driver.title.find("订单确认页") == -1: # driver.title.find寻找索引页,如果找不到返回-1,找到返回索引页# 下单按钮button = self.driver.find_element(By.XPATH,'/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div[3]/div[9]/div/div[3]/div[3]').textif button == "提交缺货登记": # 这里也就是说不一定会是"不,立即购票"这几个字,也有可能会是提交缺货登记等self.driver.refresh()elif button == "不,立即购票":self.driver.find_element(By.XPATH,'/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div[3]/div[9]/div/div[3]/div[3]').click()time.sleep(10)elif button == "不,选座购票":self.driver.find_element(By.XPATH,'/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div[3]/div[9]/div/div[3]/div[3]').click()self.status = 2else:self.status = 3tittle = self.driver.titleif tittle == "选择座位":print("###请选择座位###")time.sleep(10)self.driver.find_element('//*[@id="root"]/div/div[4]/div[2]/button').click()elif tittle == "订单确认页":while True:print("###正在加载中###")self.order_check()break

其实这里如果不是企业级的项目,而是自用的话,可以直接通过selenium语句去写观影人等信息。

 # self.driver.find_element(By.XPATH,'//*[@id="dmViewerBlock_DmViewerBlock"]/div/div/div[3]').click()# name = self.driver.find_element(By.XPATH,'//*[@id="addholder-model"]/div/div[1]/div/div[1]/input').clear().send_keys("your_name")# testify = self.driver.find_element(By.XPATH,'//*[@id="addholder-model"]/div/div[1]/div/div[5]/input').clear().send_keys("your_password")
# self.driver.find_element(By.XPATH,'//*[@id="addholder-model"]/div/div[1]/div/div[8]/div').click()
# time.sleep(2)
# self.driver.find_element(By.XPATH,'//*[@id="dmViewerBlock_DmViewerBlock"]/div[2]/div/div/div[2]/i').click()

我们来看order_check()这个方法的具体实现,其实就是勾选观影人(通过selenium去定位接口)然后提交订单即可。

    def order_check(self):print("###开始确认订单###")try:self.driver.find_element(By.XPATH, '//*[@id="dmViewerBlock_DmViewerBlock"]/div[2]/div/div/div[2]/i').click()except Exception as e:print("###购票人信息选择失败,请重新选择元素###")print(e)time.sleep(0.5)shoujihao = self.driver.find_element(By.XPATH,'//*[@id="dmContactBlock_DmContactBlock"]/div[2]/div/div[2]/input').clear()time.sleep(2)self.driver.find_element(By.XPATH,'//*[@id="dmContactBlock_DmContactBlock"]/div[2]/div/div[2]/input').send_keys("your_iphone_number")time.sleep(2)self.driver.find_element(By.XPATH, '//*[@id="dmOrderSubmitBlock_DmOrderSubmitBlock"]/div[2]/div/div[2]/div[2]/div[2]').click()time.sleep(10)

以上就是实现大麦网自动抢票的全部代码实现,其实逻辑来讲并不复杂,主要就是selenium的一些应用,最重要的是我们需要学习当中的面向对象的思想以及逻辑的复现,这是我们需要我们掌握并且要攻克的难点。

四、代码优化与注意事项

1、元素定位:要准确的使用xpath或者其他定位方式(如CSS选择器)来定位页面元素,因为大麦网也买你可能会更新,元素的xpath语法可能会改变,所以需要定期检查和调整代码。

2、等待时间:合理设置等待的时间,避免因为也页面加载缓慢导致操作失败,但也不能设置过长的时间影响抢票效率。可以使用selenium中的显示等待和隐式等待来优化。

3、多线程:可以考虑使用多线程技术,同时监控多个场次或者多个门票的抢购情况,提高抢票成功的概率,但要注意大麦网的相关规则,避免被判定为异常操作。

五、全部代码

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import os
import pickle
# 自动登录
# 大麦网首页
damai_url = "https://www.damai.cn/"
# 登录页面网址
login_url = "https://passport.damai.cn/login?ru=https%3A%2F%2Fwww.damai.cn%2F"
# 要抢票的网址
target_url = "https://detail.damai.cn/item.htm?spm=a2oeg.home.card_0.ditem_3.591b23e11Li5yj&id=862317821501"class Concert:def __init__(self):self.status = 0 # 状态,表示当前操作执行到哪一步self.login_method = 1 # 0:模拟登录 1:使用cookie登录self.driver = webdriver.Chrome()"""cookies:登陆网站的时候出现的,记录用户信息"""def set_cookies(self):self.driver.get(login_url)print("###请扫码登陆###")time.sleep(10)print("###登陆成功###")pickle.dump(self.driver.get_cookies(), open('cookie.pkl','wb')) #获取登陆的信息,并保存下来print("###cookie保存成功###")# 登陆成功后就跳转到抢票页面self.driver.get(target_url)# self.zhanghao = self.driver.find_element(By.XPATH, '//*[@id="fm-login-id"]').send_keys("17719114890")# self.mima = self.driver.find_element(By.XPATH, '//*[@id="fm-login-password"]').send_keys("dwq0219423")# self.button = self.driver.find_element(By.XPATH, '//*[@id="fm-login-submit"]').click()# time.sleep(2)# 如果文件中已经有了cookie.pkl文件def get_cookie(self):cookies = pickle.load(open('cookie.pkl','rb'))for cookie in cookies:cookie_dict = {"domain":".damai.cn","name":cookie.get("name"),"value":cookie.get("value"),}self.driver.add_cookie(cookie_dict)time.sleep(10) # 在这里记得手动刷新一下,用户信息才会显示出来print("###载入cookie成功###")"""登录"""def login(self):# 如果为0,模拟登录if self.login_method == 0:self.driver.get(login_url)elif self.login_method == 1:# 如果当前目录下没有这个cookie.pkl文件if not os.path.exists('cookie.pkl'):# 登陆一下记录登录信息self.set_cookies()else:self.driver.get(target_url)# 登陆一下 通过selenium传入一些信息self.get_cookie()"""打开浏览器"""def enter_concert(self):print("###打开浏览器,进入大麦网###")# 调用登录self.login()self.driver.refresh()self.status = 1print("###登陆成功###")# 抢票并下单:首先判断是否能够购买,如果不能就一直刷新网页,知道能够购买为止def choose_ticket(self):if self.status == 1:print("="*30)print("###请选择日期以及票价###")while self.driver.title.find("订单确认页") == -1: # driver.title.find寻找索引页,如果找不到返回-1,找到返回索引页# 下单按钮button = self.driver.find_element(By.XPATH,'/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div[3]/div[9]/div/div[3]/div[3]').textif button == "提交缺货登记": # 这里也就是说不一定会是"不,立即购票"这几个字,也有可能会是提交缺货登记等self.driver.refresh()elif button == "不,立即购票":self.driver.find_element(By.XPATH,'/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div[3]/div[9]/div/div[3]/div[3]').click()time.sleep(10)elif button == "不,选座购票":self.driver.find_element(By.XPATH,'/html/body/div[2]/div/div[1]/div[1]/div/div[2]/div[3]/div[9]/div/div[3]/div[3]').click()self.status = 2else:self.status = 3tittle = self.driver.titleif tittle == "选择座位":print("###请选择座位###")time.sleep(10)self.driver.find_element('//*[@id="root"]/div/div[4]/div[2]/button').click()elif tittle == "订单确认页":while True:print("###正在加载中###")self.order_check()break# 实现下单的逻辑# self.driver.find_element(By.XPATH,'//*[@id="dmViewerBlock_DmViewerBlock"]/div/div/div[3]').click()# name = self.driver.find_element(By.XPATH,'//*[@id="addholder-model"]/div/div[1]/div/div[1]/input').clear().send_keys("your_name")# testify = self.driver.find_element(By.XPATH,'//*[@id="addholder-model"]/div/div[1]/div/div[5]/input').clear().send_keys("your_password")# self.driver.find_element(By.XPATH,'//*[@id="addholder-model"]/div/div[1]/div/div[8]/div').click()# time.sleep(2)# self.driver.find_element(By.XPATH,'//*[@id="dmViewerBlock_DmViewerBlock"]/div[2]/div/div/div[2]/i').click()def order_check(self):print("###开始确认订单###")try:self.driver.find_element(By.XPATH, '//*[@id="dmViewerBlock_DmViewerBlock"]/div[2]/div/div/div[2]/i').click()except Exception as e:print("###购票人信息选择失败,请重新选择元素###")print(e)time.sleep(0.5)shoujihao = self.driver.find_element(By.XPATH,'//*[@id="dmContactBlock_DmContactBlock"]/div[2]/div/div[2]/input').clear()time.sleep(2)self.driver.find_element(By.XPATH,'//*[@id="dmContactBlock_DmContactBlock"]/div[2]/div/div[2]/input').send_keys("your_iphone_number")time.sleep(2)self.driver.find_element(By.XPATH, '//*[@id="dmOrderSubmitBlock_DmOrderSubmitBlock"]/div[2]/div/div[2]/div[2]/div[2]').click()time.sleep(10)if __name__ == '__main__':concert = Concert()concert.enter_concert()concert.choose_ticket()

六、总结

通过使用chromedriver和selenium库,我们可以编写一个简单的大麦网自动抢票脚本。但要注意,自动抢票可能存在违反平台规则以及法律风险等情况,在使用时需要谨慎并确保自己的行为合法合规。同时,也希望票务平台能够不断优化售票机制,让更多真正有需求的用户能够公平的购买到门票。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87903.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87903.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87903.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2048小游戏实现

2048小游戏实现 将创建一个完整的2048小游戏,包含游戏核心逻辑和美观的用户界面。设计思路 4x4网格布局响应式设计,适配不同设备分数显示和最高分记录键盘控制(方向键)和触摸滑动支持游戏状态提示(胜利/失败&#xff0…

Windows VMWare Centos Docker部署Springboot + mybatis + MySql应用

前置文章 Windows VMWare Centos环境下安装Docker并配置MySqlhttps://blog.csdn.net/u013224722/article/details/148928081 Windows VMWare Centos Docker部署Springboot应用https://blog.csdn.net/u013224722/article/details/148958480 Windows VMWare Centos Docker部署…

【科普】Cygwin与wsl与ssh连接ubuntu有什么区别?DIY机器人工房

Cygwin、WSL(Windows Subsystem for Linux)和通过 SSH 连接 Ubuntu 是三种在 Windows 环境下与类 Unix/Linux 系统交互的工具,但它们的本质、运行环境、功能范围有显著区别。以下从核心定义、关键差异和适用场景三个维度详细说明:…

Web前端数据可视化:ECharts高效数据展示完全指南

Web前端数据可视化:ECharts高效数据展示完全指南 当产品经理拿着一堆密密麻麻的Excel数据走向你时,你知道又到了"化腐朽为神奇"的时刻。数据可视化不仅仅是把数字变成图表那么简单,它是将复杂信息转化为直观洞察的艺术。 在过去两…

# IS-IS 协议 | LSP 传输与链路状态数据库同步机制

略作整理,待校。 SRM 和 SSN 标志的作用 SRM 标志 功能:SRM 标志用于跟踪路由器从一个接口向邻居发送链路状态协议数据单元(LSP)的状态。作用:确保 LSP 的正确传输和状态跟踪。 SSN 标志 广播网络 功能&#xff1…

Windows DOS CMD 100

1. systeminfo:显示系统详细信息(安装日期/补丁/内存等) 2. sfc /scannow:扫描并修复系统文件损坏 [管理员] 3. chkdsk /f:检查磁盘错误并修复(需重启) [管理员] 4. cleanmgr:启动…

HTML初学者第三天

<1>文档类型声明标签——<!DOCTYPE><!DOCTYPE>文档声明&#xff0c;作用是告诉浏览器使用哪种HTML版本来显示网页。<!DOCTYPE html>这句代码的意思是&#xff1a;当前页面采用的是HTML5版本来显示网页。注意&#xff1a;-<!DOCTYPE>声明位于文档…

学车笔记6

“不踩离合利用发动机制动”是指在驾驶过程中&#xff0c;驾驶员抬起油门踏板&#xff0c;但不踩下离合器踏板&#xff0c;利用发动机自身的阻力来减缓车辆速度的一种制动方式。具体介绍如下&#xff1a; #### 原理 - **动力传递反向**&#xff1a;正常情况下&#xff0c;发动…

人体坐姿检测系统项目教程(YOLO11+PyTorch+可视化)

&#x1f4a1;本文主要内容&#xff1a;本项目基于YOLO11深度学习目标检测算法&#xff0c;设计并实现了一个人体坐姿检测系统。系统能够自动识别图像或视频中的多种坐姿类型&#xff08;如&#xff1a;正常坐姿、不良坐姿等&#xff09;&#xff0c;为健康监测、智能教室、办公…

服务网格可观测性深度实践与创新优化

主题&#xff1a;突破服务网格监控瓶颈——基于eBPF的无侵入式全链路可观测性实践 技术领域&#xff1a;云原生/微服务/服务网格&#xff08;Service Mesh&#xff09; 一、问题背景&#xff1a;传统服务网格监控的痛点 在Istio、Linkerd等服务网格架构中&#xff0c;可观测…

微信小程序41~50

1.列表渲染-进阶用法 如果要对默认的变量名和下标进行修改&#xff0c;可以使用wx:for-item和wx:for-index wx:for-item可以指定数组当前元素的变量名 wx:for-index可以指定数组当前下标的变量名将wx:for用在标签上&#xff0c;以渲染一个包含多个节点的结构快 并不是一个组件…

向量数据库-Milvus快速入门

Milvus 概述 向量是神经网络模型的输出数据格式&#xff0c;可以有效地对信息进行编码&#xff0c;在知识库、语义搜索、检索增强生成&#xff08;RAG&#xff09;等人工智能应用中发挥着举足轻重的作用。 Milvus 是一个开源的向量数据库&#xff0c;适合各种规模的人…

uniapp的光标跟随和打字机效果

1、准备好容器文字的显示textRef&#xff0c;以及光标的显示 &#xff0c;使用transform-translate对光标进行移动到文字后面<template><view class"container" ref"contentRef"><u-parse :content"nodeText" ref"textRef&q…

「ECG信号处理——(21)基于Pan-Tompkins和随机森林(RF)的睡眠呼吸暂停检测算法」2025年7月4日

目录 1、引言 2、数据库介绍&#xff08;Apnea-ECG Database) 3、基于Pan-Tompkins和随机森林&#xff08;RF&#xff09;的睡眠呼吸暂停检测算法 3.1 算法概述 3.2 心电信号预处理及QRS波检测算法 3.3 心电信号的随机森林睡眠呼吸暂停识别 4、实验结果 4.1 心电信号预处理及QR…

C++学习之STL学习:list的模拟实现

在上一篇学习了list的使用后&#xff0c;在本篇我们将通过模拟实现的方式深入了解list的底层运作原理。 作者的个人gitee&#xff1a;楼田莉子 (riko-lou-tian) - Gitee.com 感兴趣的读者可以看一看 目录 前置准备 结点的定义 链表类的定义 迭代器 普通迭代器 const迭代器 …

不引入变量 异或交换的缺点

文章目录选择排序正确代码交换两个数位置的方法引入中间变量不引入中间变量&#xff0c;使用异或的方法错误原因优化代码选择排序正确代码 // 数组中交换i和j位置的数public static void swap(int[] arr, int i, int j) {int tmp arr[i];arr[i] arr[j];arr[j] tmp;}// 选择排…

VS Code中使用Git的方法:环境配置与Git操作

本文介绍在Windows电脑的VS Code中&#xff0c;配置Git环境并使用Git命令、功能的方法。 1 环境部署 首先&#xff0c;我们需要分别安装Git环境与VS Code软件。这里需要注意&#xff0c;即使是在VS Code中使用Git&#xff0c;也需要我们首先在电脑上单独配置好Git的环境&#…

在 Windows 上安装和运行 Apache Kafka

Apache Kafka是一款开源应用程序&#xff0c;用于实时处理海量数据流。Apache Kafka 是一个发布-订阅消息系统。消息系统允许您在进程、应用程序和服务器之间发送消息。广义上讲&#xff0c;Apache Kafka 是一款可以定义主题并进行进一步处理的软件。 下载和安装 Apache Kafk…

【嵌入式电机控制#8】编码器测速实战

一、编码器测速重要参数有刷电机编码器参数&#xff08;其他的后面会慢慢提及&#xff0c;也可以在某宝看&#xff09;1. 编码器分辨率&#xff08;PPR&#xff09;2. 编码器工作电压 3. 电机减速比 例如 30&#xff1a;1 指的就是电机减速轴转1圈&#xff0c;编码器转30圈。注…

在C#中,可以不实例化一个类而直接调用其静态字段

这是因为静态成员&#xff08;static members&#xff09;属于类本身&#xff0c;而不是类的实例。这是静态成员的核心特性1. 静态成员属于类&#xff0c;而非实例当用static关键字修饰字段、方法或属性时&#xff0c;这些成员会绑定到类级别&#xff0c;而不是实例级别。它们在…