爬虫笔记20——票星球抢票脚本的实现

以下内容仅供交流学习使用!!!

思路分析

前面的爬虫笔记一步一步走过来我们的技术水平也有了较大的提升了,现在我们来进行一下票星球抢票实战项目,实现票星球的自动抢票。

  1. 我们打开票星球的移动端页面,分析每一步操作需要用到的接口。
  2. 先手动操作抢票找到抢票流程的每一个接口后,判断接口请求要求,请求方式,以及是否需要传递什么参数。
  3. 接下来就是每个接口一步一步操作请求响应,然后成功返回200即可。
  4. 然后实现过程主要是创建一个类对象,配置需要用到的属性,每一步操作封装成每一个函数,最后用一个主函数运行。
  5. 当然,下面是代码的大体内容,主要讲解如何操作,需要全部代码可以找一下我发布的资源下载。

示例代码

首先我们要用到下面三个包,pip下载即可

#pip install requests fake_useragent datetime
#请求
import requests
#随机UA
from fake_useragent import UserAgent
#时间
import datetime

然后我们创建一个类对象,初始化方法里面创建需要用到的属性变量:

class PXQ:def __init__(self):# 输入自己的tokenself.token = '这里要打开网页开发者工具找到你自己的token'# 演唱会项目id,必填,最简单就是在url上可以看到,下面这个是要操作抢购的演唱会的show_id# 或者也是打开网页开发者工具中的网络也是可以找到self.show_id = '665708481d06bc0001627d83'# 指定场次id,不指定则默认从第一场开始遍历,查找同理self.session_id = '665708656a025300012ae72a'# 购票数量,自行设置要购买的数量,但一定要看购票须知,不要超过上限self.buy_count = 1# 指定观演人,观演人序号从0开始,人数需与票数保持一致self.audience_idx = [0]# audience_idx = [0]# 门票类型,不确定则可以不填,让系统自行判断。快递送票:EXPRESS,电子票:E_TICKET/ID_CARD,现场取票:VENUE,电子票或现场取票:VENUE_E,目前只发现这四种,如有新发现可补充self.deliver_method = ''# 获取想要购买的票价idself.seat_plan_id = ''self.session_id_exclude = []  # 被排除掉的场次self.price: int = 0# 抢购的票价名称self.seatPlanName = ''self.threadsLists = []# 判断是否对应价位有票数,默认是无self.flag = False# 设置抢票开始时间,自行设置开抢时间,分别是年月日时分秒self.startTime = datetime.datetime(2024, 7, 3, 2, 0, 0)# 随机UAself.user_agent = UserAgent()

接下来就是操作流程每个请求接口设置,封装成方法,依次是:

  • 根据项目id获取所有场次和在售状态
    # 根据项目id获取所有场次和在售状态def get_sessions(self, useragent):headers = {'User-Agent': useragent,'Content-Type': 'application/json'}url = "https://m.piaoxingqiu.com/cyy_gatewayapi/show/pub/v3/show/" + self.show_id + "/sessions_dynamic_data"response = requests.get(url=url, headers=headers).json()if response["statusCode"] == 200:# 获取场次的id# print(response)return response["data"]["sessionVOs"]else:print("get_sessions异常:" + str(response))return None
  • 根据场次id获取座位信息,箭头后面表示函数返回数据类型
    def get_seat_plans(self, useragent) -> list:headers = {'User-Agent': useragent,'Content-Type': 'application/json'}url = "https://m.piaoxingqiu.com/cyy_gatewayapi/show/pub/v3/show/" + self.show_id + "/show_session/" + self.session_id + "/seat_plans_static_data"response = requests.get(url=url, headers=headers).json()if response["statusCode"] == 200:# 查看票价的id# print(response)return response["data"]["seatPlans"]else:raise Exception("get_seat_plans异常:" + str(response))
  • 获取座位余票
# 获取座位余票def get_seat_count(self, useragent) -> list:headers = {'User-Agent': useragent,'Content-Type': 'application/json'}url = "https://m.piaoxingqiu.com/cyy_gatewayapi/show/pub/v3/show/" + self.show_id + "/show_session/" + self.session_id + "/seat_plans_dynamic_data"response = requests.get(url=url, headers=headers).json()if response["statusCode"] == 200:return response["data"]["seatPlans"]else:raise Exception("get_seat_count异常:" + str(response))
  • 获取门票类型(快递送票EXPRESS,电子票E_TICKET,现场取票VENUE,电子票或现场取票VENUE_E)
# 获取门票类型(快递送票EXPRESS,电子票E_TICKET,现场取票VENUE,电子票或现场取票VENUE_E)def get_deliver_method(self, useragent, qty: int) -> str:headers = {'User-Agent': useragent,'Content-Type': 'application/json','access-token': self.token}data = {"items": [{"skus": [{"seatPlanId": self.seat_plan_id,  "sessionId": self.session_id,  "showId": self.show_id,  "skuId": self.seat_plan_id,"skuType": "SINGLE","ticketPrice": self.price, "qty": qty  #数量}],"spu": {"id": self.show_id,"spuType": "SINGLE"}}]}url = "https://m.piaoxingqiu.com/cyy_gatewayapi/trade/buyer/order/v3/pre_order"response = requests.post(url=url, headers=headers, json=data).json()if response["statusCode"] == 200:# 这里的print可以去掉# print(response["data"]["supportDeliveries"][0])return response["data"]["supportDeliveries"][0]["name"]else:raise Exception("获取门票类型异常:" + str(response))
  • 获取观演人信息
# 获取观演人信息# def get_audiences() -> list | None:def get_audiences(self, useragent):headers = {'User-Agent': useragent,'Content-Type': 'application/json','access-token': self.token}url = "https://m.piaoxingqiu.com/cyy_gatewayapi/user/buyer/v3/user_audiences"response = requests.get(url=url, headers=headers).json()if response["statusCode"] == 200:# 可以获取观影人的信息查看是否正确return response["data"]else:print("get_audiences异常:" + str(response))return None
  • 提交订单需要做的判断比较多,要判断演出票是什么票型(快递送票EXPRESS,电子票E_TICKET/ID_Card,现场取票VENUE,电子票或现场取票VENUE_E)
# 提交订单(快递送票EXPRESS,电子票E_TICKET/ID_Card,现场取票VENUE,电子票或现场取票VENUE_E)def create_order(self, useragent, qty: int, express_fee: int,receiver, cellphone, address_id, detail_address, location_city_id, audience_ids: list):headers = {'User-Agent': useragent,'Content-Type': 'application/json','access-token': self.token}if self.deliver_method == "EXPRESS":data = {"priceItemParam": [{"applyTickets": [],"priceItemName": "票款总额","priceItemVal": self.price * qty,"priceItemType": "TICKET_FEE","priceItemSpecies": "SEAT_PLAN","direction": "INCREASE","priceDisplay": "¥" + str(self.price * qty)},{"applyTickets": [],"priceItemName": "快递费","priceItemVal": express_fee,"priceItemId": self.show_id,"priceItemSpecies": "SEAT_PLAN","priceItemType": "EXPRESS_FEE","direction": "INCREASE","priceDisplay": "¥" + str(express_fee)}],"items": [{"skus": [{"seatPlanId": self.seat_plan_id,"sessionId": self.session_id,"showId": self.show_id,"skuId": self.seat_plan_id,"skuType": "SINGLE","ticketPrice": self.price,"qty": qty,"deliverMethod": self.deliver_method}],"spu": {"id": self.show_id,"spuType": "SINGLE"}}],"contactParam": {"receiver": receiver,  # 张三"cellphone": cellphone  # 13812345678},"one2oneAudiences": [{"audienceId": i, "sessionId": self.session_id} for i in audience_ids],"addressParam": {"address": detail_address,  # 星巴克咖啡门口"district": location_city_id[4:],"city": location_city_id[2:4],"province": location_city_id[0:2],"addressId": address_id}}elif self.deliver_method == "ID_CARD":data = {"priceItemParam": [{"applyTickets": [],"priceItemName": "票款总额","priceItemVal": self.price * qty,"priceItemType": "TICKET_FEE","priceItemSpecies": "SEAT_PLAN","direction": "INCREASE","priceDisplay": "¥" + str(self.price * qty),}],"items": [{"skus": [{"seatPlanId": self.seat_plan_id,"sessionId": self.session_id,"showId": self.show_id,"skuId": self.seat_plan_id,"skuType": "SINGLE","ticketPrice": self.price,"qty": qty,"deliverMethod": self.deliver_method,}],"spu": {"id": self.show_id, "spuType": "SINGLE"},}],"one2oneAudiences": [{"audienceId": i, "sessionId": self.session_id} for i in audience_ids],"many2OneAudience": {"audienceId": audience_ids[0],"sessionIds": [self.session_id],},}# 电子票已解决elif self.deliver_method == "E_TICKET":data = {"priceItemParam": [{"applyTickets": [],"priceItemName": "票款总额","priceItemVal": self.price * qty,"priceItemType": "TICKET_FEE","priceItemSpecies": "SEAT_PLAN","direction": "INCREASE","priceDisplay": "¥" + str(self.price * qty)}],"items": [{"skus": [{"seatPlanId": self.seat_plan_id,"sessionId": self.session_id,"showId": self.show_id,"skuId": self.seat_plan_id,"skuType": "SINGLE","ticketPrice": self.price,"qty": qty,"deliverMethod": self.deliver_method}],"spu": {"id": self.show_id,"spuType": "SINGLE"}}],"many2OneAudience": {"audienceId": audience_ids[0],"sessionIds": [self.session_id]}}elif self.deliver_method == "VENUE":data = {"priceItemParam": [{"applyTickets": [],"priceItemName": "票款总额","priceItemVal": self.price * qty,"priceItemType": "TICKET_FEE","priceItemSpecies": "SEAT_PLAN","direction": "INCREASE","priceDisplay": "¥" + str(self.price * qty)}],"items": [{"skus": [{"seatPlanId": self.seat_plan_id,"sessionId": self.session_id,"showId": self.show_id,"skuId": self.seat_plan_id,"skuType": "SINGLE","ticketPrice": self.price,"qty": qty,"deliverMethod": self.deliver_method}],"spu": {"id": self.show_id,"spuType": "SINGLE"}}],"one2oneAudiences": [{"audienceId": i, "sessionId": self.session_id} for i in audience_ids]}elif self.deliver_method == "VENUE_E":data = {"priceItemParam": [{"applyTickets": [],"priceItemName": "票款总额","priceItemVal": self.price * qty,"priceItemType": "TICKET_FEE","priceItemSpecies": "SEAT_PLAN","direction": "INCREASE","priceDisplay": "¥" + str(self.price * qty)}],"items": [{"skus": [{"seatPlanId": self.seat_plan_id,"sessionId": self.session_id,"showId": self.show_id,"skuId": self.seat_plan_id,"skuType": "SINGLE","ticketPrice": self.price,"qty": qty,"deliverMethod": self.deliver_method}],"spu": {"id": self.show_id,"spuType": "SINGLE"}}]}else:raise Exception("不支持的deliver_method:" + str(self.deliver_method))url = "https://m.piaoxingqiu.com/cyy_gatewayapi/trade/buyer/order/v3/create_order"response = requests.post(url=url, headers=headers, json=data).json()if response["statusCode"] == 200:print("下单成功!请尽快支付!")else:raise Exception("下单异常:" + str(response))
  • 主函数,前面都是函数定义,主要是在主函数执行操作抢票。
  • 我们前面已经知道哪个演唱会show_id,以及哪个场次session_id,现在要在主函数里面的seat_plan_id进行自行赋值,也可以开头初始化方法里面赋值/默认为空,seat_plan_id可以通过前面get_seat_plans函数里的接口地址获取。
# 主函数def main(self):# 创建随机的useragentuseragent = self.user_agent.randomwhile True:try:# 获取座位余票信息,默认从最低价开始seat_plans = self.get_seat_plans(useragent)# print(seat_plans)seat_count = self.get_seat_count(useragent)# print(seat_count)# 获取想要购买的票价idself.seat_plan_id = '667ba34a090ca100015604df'# 提取出对应的票价for temp in seat_plans:if temp["seatPlanId"] == self.seat_plan_id:self.price = temp["originalPrice"]self.seatPlanName = temp["seatPlanName"]break# 判断对应的票价id是否有剩余票数for i in seat_count:if i["seatPlanId"] == self.seat_plan_id:if i["canBuyCount"] > 0:self.flag = True# print(f'{self.seatPlanName}该价位剩余数量:可满足您的购买需求')breakelse:self.flag = False# print(f'{self.seatPlanName}无剩余!')breakif self.flag:print(f'{self.seatPlanName}该价位剩余数量:可满足您的购买需求')print('正在努力抢购中……')else:print(f'{self.seatPlanName}票价无剩余!,将继续为你刷新抢购')continueif not self.deliver_method:self.deliver_method = self.get_deliver_method(useragent, self.buy_count)print("演唱票类型:" + self.deliver_method)if self.deliver_method == "VENUE_E":self.create_order(useragent, self.buy_count, 0, None, None, None, None, None, [])else:# 获取观演人信息audiences = self.get_audiences(useragent)if len(self.audience_idx) == 0:self.audience_idx = range(self.buy_count)audience_ids = [audiences[i]["id"] for i in self.audience_idx]if self.deliver_method == "EXPRESS":# 获取默认收货地址address = self.get_address(useragent)address_id = address["addressId"]  # 地址idlocation_city_id = address["locationId"]  # 460102receiver = address["username"]  # 收件人cellphone = address["cellphone"]  # 电话detail_address = address["detailAddress"]  # 详细地址# 获取快递费用express_fee = self.get_express_fee(useragent, self.buy_count, location_city_id)self.create_order(useragent, self.buy_count, express_fee["priceItemVal"], receiver,cellphone, address_id, detail_address, location_city_id, audience_ids)elif self.deliver_method == "VENUE" or self.deliver_method == "E_TICKET" or self.deliver_method == "ID_CARD":self.create_order(useragent, self.buy_count, 0, None, None, None, None, None, audience_ids)else:print("不支持的deliver_method:" + self.deliver_method)breakexcept Exception as e:print(e)

以上内容全是定义在一个类中,我们要使用那就要创建一个类对象,现在我们打开一个文件入口进行创建:

if __name__ == '__main__':# 创建对象pxq = PXQ()while True:now = datetime.datetime.now()# 判断当前时间与设置的开抢时间,并进行倒计时,当当前时间大于开抢时间直接开抢if now < pxq.startTime:print(f"{int(pxq.startTime.timestamp()-now.timestamp())}秒后开抢", end="\r")else:pxq.main()break

执行前我们配置好show_id,session_id和seat_plan_id,运行起来根据你设置的抢购时间在等待抢购的:
在这里插入图片描述

获取seat_plan_id的流程操作:
在这里插入图片描述
抢票成功会显示:
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

视频字幕提取在线工具有哪些?总结5个字幕提取工具

平时在沉浸式追剧的时候&#xff0c;我们常常都会被影视剧中的各种金句爆梗而逗得开怀大笑~而真正要用到时候却总是一片头脑空白。其实要记住它们最好的办法便是将其提取留档下来&#xff0c;每次有需要的时候打开就能一下子回顾到~ 今天就来带大家盘一盘视频字幕提取的软件好…

高考假期预习指南

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

Rust: polars行遍历,从dataframe到struct及Bar设计比较

pandas提供了iterrows()、itertuples()、apply等行遍历的方式&#xff0c;还是比较方便的。 polars的列操作功能非常强大&#xff0c;这个在其官网上有详细的介绍。由于polars底层的arrow是列存储模式&#xff0c;行操作效率低下&#xff0c;官方也不推荐以行方式进行数据操作。…

react_后台管理_项目

目录 1.运行项目 2. 项目结构 ①项目顶部导航栏 ②项目左侧导航栏 ③主页面-路由切换区 本项目使用的是 reacttsscss 技术栈。 1.运行项目 在当前页面顶部下载本项目&#xff0c;解压后使用编辑器打开&#xff0c;然后再终端输入命令&#xff1a; npm i 下载依赖后&am…

【应急响应】Windows应急响应 - 基础命令篇

前言 在如今的数字化时代&#xff0c;Windows系统面对着越来越复杂的网络威胁和安全挑战。本文将深入探讨在Windows环境下的实战应急响应策略。我们将重点关注实际应急响应流程、关键工具的应用&#xff0c;以及如何快速准确地识别和应对安全事件。通过分享实际案例分析&#…

FIO压测磁盘性能以及需要注意的问题

一、压测类型 1、顺序读&#xff08;IO&#xff09;&#xff1a;read&#xff0c;bs1M&#xff0c;job数从1开始往上加&#xff1a;2、3、4... 2、顺序写&#xff08;IO&#xff09;&#xff1a;write&#xff0c;bs1M&#xff0c;job数从1开始往上加&#xff1a;2、3、4... …

【ACM出版,马来西亚-吉隆坡举行】第四届互联网技术与教育信息化国际会议 (ITEI 2024)

作为全球科技创新大趋势的引领者&#xff0c;中国不断营造更加开放的科技创新环境&#xff0c;不断提升学术合作的深度和广度&#xff0c;构建惠及各方的创新共同体。这是对全球化的新贡献&#xff0c;是构建人类命运共同体的新贡献。 第四届互联网技术与教育信息化国际学术会议…

【C++知识点总结全系列 (07)】:模板与泛型编程详细总结与分析

模板与泛型编程 1、概述(1)What&#xff08;什么是模板、泛型编程&#xff09;(2)Why(3)Which(4)模板参数A.WhatB.HowC.模板参数的类型成员D.默认模板参数 2、模板函数3、模板类(1)How&#xff08;如何定义和使用模板类&#xff09;(2)成员模板 4、模板实参推断(1)What&#xf…

昇思25天学习打卡营第7天|Pix2Pix实现图像转换

文章目录 昇思MindSpore应用实践基于MindSpore的Pix2Pix图像转换1、Pix2Pix 概述2、U-Net架构定义UNet Skip Connection Block 2、生成器部分3、基于PatchGAN的判别器4、Pix2Pix的生成器和判别器初始化5、模型训练6、模型推理 Reference 昇思MindSpore应用实践 本系列文章主要…

Python基础003

Python流程控制基础 1.条件语句 内置函数input a input("请输入一段内容&#xff1a;") print(a) print(type(a))代码执行的时候遇到input函数&#xff0c;就会等键盘输入结果&#xff0c;已回车为结束标志&#xff0c;也就时说输入回车后代码才会执行 2.顺序执行…

pandas数据分析(5)

pandas使用Numpy的np.nan代表缺失数据&#xff0c;显示为NaN。NaN是浮点数标准中地Not-a-Number。对于时间戳&#xff0c;则使用pd.NaT&#xff0c;而文本使用的是None。 首先构造一组数据&#xff1a; 使用None或者np.nan来表示缺失的值&#xff1a; 清理DataFrame时&#xf…

解决数据库PGSQL,在Mybatis中创建临时表报错TODO IDENTIFIER,连接池用的Druid。更换最新版本Druid仍然报错解决

Druid版本1.1.9报错Caused by: java.sql.SQLException: sql injection violation, syntax error: TODO IDENTIFIER : CREATE TEMPORARY TABLE temp_ball_classify (id int8 NOT NULL,create_time TIMESTAMP,create_by VARCHAR,classify_name VARCHAR) 代码如下&#xff1a; 测…

四川蔚澜时代电子商务有限公司打造抖音电商服务新高地

在数字化浪潮汹涌澎湃的今天&#xff0c;电商行业以其独特的魅力和强大的市场潜力&#xff0c;成为了推动经济增长的新引擎。四川蔚澜时代电子商务有限公司&#xff0c;作为这个领域的佼佼者&#xff0c;正以其专业的服务、创新的理念和卓越的实力&#xff0c;引领抖音电商服务…

用AI,每天创作200+优质内容,2分钟教会你操作!

前段时间发布了这篇“寻找爆款文案及标题的9大渠道&#xff0c;直接搬运都能搞流量&#xff01;”&#xff0c;里面我讲到如何寻找爆款标题。最近不少朋友问我&#xff0c;如何创作这个标题相关的内容。 多数平台都有风控规则&#xff0c;有些平台内容也会有字数要求。为了让大…

SpringBoot 项目整合 MyBatis 框架,附带测试示例

文章目录 一、创建 SpringBoot 项目二、添加 MyBatis 依赖三、项目结构和数据库表结构四、项目代码1、application.yml2、TestController3、TbUser4、TbUserMapper5、TestServiceImpl6、TestService7、TestApplication8、TbUserMapper.xml9、MyBatisTest 五、浏览器测试结果六、…

JavaScript实现时钟计时

会动的时钟 1.目标 2.分析 1.最开始页面不显示时间&#xff0c;有两个按钮 开始 暂停。开始按钮是可以点击的&#xff0c;暂停按钮不能点击 2.当点击开始按钮后&#xff0c;设置开始按钮不可用&#xff0c;暂停按钮可用。然后将当前系统时间放到按钮上面。每隔1秒中更新一下…

TransMIL:基于Transformer的多实例学习

MIL是弱监督分类问题的有力工具。然而&#xff0c;目前的MIL方法通常基于iid假设&#xff0c;忽略了不同实例之间的相关性。为了解决这个问题&#xff0c;作者提出了一个新的框架&#xff0c;称为相关性MIL&#xff0c;并提供了收敛性的证明。基于此框架&#xff0c;还设计了一…

3.js - 反射率(reflectivity) 、折射率(ior)

没啥太大的感觉 反射率 reflectivity 概念 反射率&#xff1a;指的是&#xff0c;材质表面反射光线的能力反射率&#xff0c;用于控制材质对环境光&#xff0c;或光源的反射程度反射率越高&#xff0c;材质表面反射的光线越多&#xff0c;看起来就越光亮使用 适用于&#xff0…

【PYG】Cora数据集分类任务计算损失,cross_entropy为什么不能直接替换成mse_loss

cross_entropy计算误差方式&#xff0c;输入向量z为[1,2,3]&#xff0c;预测y为[1]&#xff0c;选择数为2&#xff0c;计算出一大坨e的式子为3.405&#xff0c;再用-23.405计算得到1.405MSE计算误差方式&#xff0c;输入z为[1,2,3]&#xff0c;预测向量应该是[1,0,0]&#xff0…

Dify入门指南

一.Dify介绍 生成式 AI 应用创新引擎&#xff0c;开源的 LLM 应用开发平台。提供从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等能力&#xff0c;轻松构建和运营生成式 AI 原生应用&#xff0c;比 LangChain 更易用。一个平台&#xff0c;接入全球大型语言模型。不同…