爬虫笔记20——票星球抢票脚本的实现
以下内容仅供交流学习使用!!!
思路分析
前面的爬虫笔记一步一步走过来我们的技术水平也有了较大的提升了,现在我们来进行一下票星球抢票实战项目,实现票星球的自动抢票。
- 我们打开票星球的移动端页面,分析每一步操作需要用到的接口。
- 先手动操作抢票找到抢票流程的每一个接口后,判断接口请求要求,请求方式,以及是否需要传递什么参数。
- 接下来就是每个接口一步一步操作请求响应,测试成功返回200状态码即可。
- 实现过程我主要是创建一个类对象,初始化方法配置需要用到的属性,然后把每一步操作的请求封装成每一个函数。
- 最后定义一个主函数运行实现逻辑。
- 当然,下面是代码的大体内容,主要讲解如何操作,需要全部代码可以找一下我发布的资源下载(目前文件还在审核中,通过后即可直接下载)。
示例代码
首先我们要用到下面三个包,pip下载即可
#pip install requests fake_useragent datetime
#请求
import requests
#随机UA
from fake_useragent import UserAgent
#时间
import datetime
然后我们创建一个类对象,初始化方法里面创建需要用到的属性变量,token属性需要自行登录找到自己的token复制过来即可:
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的流程操作:
抢票成功会显示:
以上是大体的思路流程,详细的代码可以看下我发布的资源,或者找我上传到github上的资源下载。
相关文章:

爬虫笔记20——票星球抢票脚本的实现
以下内容仅供交流学习使用!!! 思路分析 前面的爬虫笔记一步一步走过来我们的技术水平也有了较大的提升了,现在我们来进行一下票星球抢票实战项目,实现票星球的自动抢票。 我们打开票星球的移动端页面,分…...

DDR3(三)
目录 1 预取1.1 什么是预取1.2 预取有哪些好处1.3 结构框图1.4 总结 2 突发2.1 什么是突发2.2 突发与预取 本文讲解DDR中常见的两个术语:预取和突发,对这两个概念理解的关键在于地址线的低位是否参与译码,具体内容请继续往下看。 1 预取 1.1…...

JDK都出到20多了,你还不会使用JDK8的Stream流写代码吗?
目录 前言 Stream流 是什么? 为什么要用Steam流 常见stream流使用案例 映射 map() & 集合 collect() 单字段映射 多字段映射 映射为其他的对象 映射为 Map 去重 distinct() 过滤 filter() Stream流的其他方法 使用Stream流的弊端 前言 当你某天看…...
QT slots 函数
文章目录 概述小结 概述 在Qt中,slots 是一种特殊的成员函数,它们可以与对象发出的信号连接。当信号被触发时,连接的槽函数会被调用。 来个简单的示例吧,如下图: #include <QObject> #include <QDebug>…...

pycharm如何使用jupyter
目录 配置jupyter新建jupyter文件别人写的方法(在pycharm种安装,在网页中使用) pycharm专业版 配置jupyter 在pycharm终端启动一个conda虚拟环境,输入 conda install jupyter会有很多前置包需要安装: 新建jupyter…...

机器学习——无监督学习(k-means算法)
1、K-Means聚类算法 K表示超参数个数,如分成几个类别,K值就取多少。若无需求,可使用网格搜索找到最佳的K。 步骤: 1、随机设置K个特征空间内的点作为初始聚类中心; 2、对于其他每个点计算到K个中心的距离,…...
强化学习-6 DDPG、PPO、SAC算法
文章目录 1 DPG方法2 DDPG算法3 DDPG算法的优缺点4 TD3算法4.1 双Q网络4.2 延迟更新4.3 噪声正则 5 附15.1 Ornstein-Uhlenbeck (OU) 噪声5.1.1 定义5.1.2 特性5.1.3 直观理解5.1.4 数学性质5.1.5 代码示例5.1.6 总结 6 重要性采样7 PPO算法8 附28.1 重要性采样方差计算8.1.1 公…...
vue3实现多表头列表el-table,拖拽,鼠标滑轮滚动条优化
需求背景解决效果index.vue 需求背景 需要实现多表头列表的用户体验优化 解决效果 index.vue <!--/** * author: liuk * date: 2024-07-03 * describe:**** 多表头列表 */--> <template><el-table ref"tableRef" height"calc(100% - 80px)&qu…...

Micron近期发布了32Gb DDR5 DRAM
Micron Technology近期发布了一项内存技术的重大突破——一款32Gb DDR5 DRAM芯片,这项创新不仅将存储容量翻倍,还显著提升了针对人工智能(AI)、机器学习(ML)、高性能计算(HPC)以及数…...
SQL Server时间转换
第一种:format --转化成年月日 select format( GETDATE(),yyyy-MM-dd) --转化年月日,时分秒,这里的HH指24小时的,hh是12小时的 select format( GETDATE(),yyyy-MM-dd HH:mm:ss) --转化成时分秒的,这里就不一样的&…...

kubernetes集群部署:node节点部署和CRI-O运行时安装(三)
关于CRI-O Kubernetes最初使用Docker作为默认的容器运行时。然而,随着Kubernetes的发展和OCI标准的确立,社区开始寻找更专门化的解决方案,以减少复杂性和提高性能。CRI-O的主要目标是提供一个轻量级的容器运行时,它可以直接运行O…...

03:Spring MVC
文章目录 一:Spring MVC简介1:说说自己对于Spring MVC的了解?1.1:流程说明: 一:Spring MVC简介 Spring MVC就是一个MVC框架,Spring MVC annotation式的开发比Struts2方便,可以直接代…...
玩转springboot之springboot注册servlet
springboot注册servlet 有时候在springboot中依然需要注册servlet,filter,listener,就以servlet为例来进行说明,另外两个也都类似 使用WebServlet注解 在servlet3.0之后,servlet注册支持注解注册,而不需要在…...

推荐好玩的工具之OhMyPosh使用
解除禁止脚本 Set-ExecutionPolicy RemoteSigned 下载Oh My Posh winget install oh-my-posh 或者 Install-Module oh-my-posh -Scope AllUsers 下载Git提示 Install-Module posh-git -Scope CurrentUser 或者 Install-Module posh-git -Scope AllUser 下载命令提示 Install-Mo…...

pydub、ffmpeg 音频文件声道选择转换、采样率更改
快速查看音频通道数和每个通道能力判断具体哪个通道说话;一般能量大的那个算是说话 import wave from pydub import AudioSegment import numpy as npdef read_wav_file(file_path):with wave.open(file_path, rb) as wav_file:params wav_file.getparams()num_cha…...

0803实操-Windows Server系统管理
Windows Server系统管理 系统管理与基础配置 查看系统信息、更改计算机名称 网络配置 启用网络发现 Windows启用网络发现是指在网络设置中启用一个功能,该功能允许您的计算机在网络上识别和访问其他设备和计算机。具体来说,启用网络发现后ÿ…...
使用Java构建物联网应用的最佳实践
使用Java构建物联网应用的最佳实践 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 随着物联网(IoT)技术的快速发展,越来越…...

价格预言机的使用总结(一):Chainlink篇
文章首发于公众号:Keegan小钢 前言 价格预言机已经成为了 DeFi 中不可获取的基础设施,很多 DeFi 应用都需要从价格预言机来获取稳定可信的价格数据,包括借贷协议 Compound、AAVE、Liquity ,也包括衍生品交易所 dYdX、PERP 等等。…...

【Pyhton】读取寄存器数据到MySQL数据库
目录 步骤 modsim32软件配置 Navicat for MySQL 代码实现 步骤 安装必要的库:确保安装了pymodbus和pymysql。 配置Modbus连接:设置Modbus从站的IP地址、端口(对于TCP)或串行通信参数(对于RTU)。 连接M…...

jmeter-beanshell学习3-beanshell获取请求报文和响应报文
前后两个报文,后面报文要用前面报文的响应结果,这个简单,正则表达式或者json提取器,都能实现。但是如果后面报文要用前面请求报文的内容,感觉有点难。最早时候把随机数写在自定义变量,前后两个接口都用这个…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
第14节 Node.js 全局对象
JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。 在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局…...