将Python作为一个便利工具的应用——抢购

前言

近来无意中看到一些Python的应用场景——抢购。这的确是一个恰当的应用,因此本文从一个开源项目库来入手分析项目是如何运行的。

结构

解析

1662716093305.png

入口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if __name__ == '__main__':
a = """

oooo oooooooooo. .oooooo..o oooo o8o oooo oooo
`888 `888' `Y8b d8P' `Y8 `888 `"' `888 `888
888 888 888 Y88bo. .ooooo. .ooooo. 888 oooo oooo 888 888
888 888 888 `"Y8888o. d88' `88b d88' `"Y8 888 .8P' `888 888 888
888 888 888 8888888 `"Y88b 888ooo888 888 888888. 888 888 888
888 888 d88' oo .d8P 888 .o 888 .o8 888 `88b. 888 888 888
.o. 88P o888bood8P' 8""88888P' `Y8bod8P' `Y8bod8P' o888o o888o o888o o888o o888o
`Y888P

功能列表:
1.预约商品
2.秒杀抢购商品
"""
print(a)

jd_seckill = JdSeckill()
choice_function = input('请选择:')
if choice_function == '1':
jd_seckill.reserve()
elif choice_function == '2':
jd_seckill.seckill_by_proc_pool()
else:
print('没有此功能')
sys.exit(1)

这一段代码很简单:

  1. 首先输出一段提示,让用户稍后选择预约还送抢购;
  2. 然后实例化jd_seckill = JdSeckill();
  3. 根据输入选择功能

主功能(预约)

接下来先看一下预约功能,调用了reserve(),这段代码使用了装饰器,判断是否登录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@check_login
def reserve(self):
"""
预约
"""
self._reserve()

@check_login
def seckill(self):
"""
抢购
"""
self._seckill()

@check_login
def seckill_by_proc_pool(self, work_count=5):
"""
多进程进行抢购
work_count:进程数量
"""
with ProcessPoolExecutor(work_count) as pool:
for i in range(work_count):
pool.submit(self.seckill)

可以看到预约、抢购和多线程抢购这些功能都使用了装饰器。

登录判断

1
2
3
4
5
6
7
8
9
10
11
def check_login(func):
"""
用户登陆态校验装饰器。若用户未登陆,则调用扫码登陆
"""
@functools.wraps(func)
def new_func(self, *args, **kwargs):
if not self.qrlogin.is_login:
logger.info("{0} 需登陆后调用,开始扫码登陆".format(func.__name__))
self.login_by_qrcode()
return func(self, *args, **kwargs)
return new_func

这里记录一下`@functools.wraps(fun)的作用,主要因为增加了装饰器的函数其实就变成了另外一个函数,__namedoc都发生了变化。因此增加了@functools.wraps(fun)`之后就可以防止此类情况的发生。

执行步骤:

首先判断self.qrlogin.is_login是否True,默认为Falseself.qrlogin = QrLogin(self.spider_session)会调用QrLogin -> SpiderSession.

QrLogin()功能:

  1. 初始化扫码目录
    1. 定义二维码文件名称
    2. 设置session
    3. 设置默认登录状态为False
    4. 刷新登录状态
  2. 刷新是否登录的状态
  3. 验证cookie(是否登录)
  4. 获取登录页面
  5. 缓存并展示登录二维码
  6. 通过token获取ticket
  7. 校验ticket
  8. 使用二维码登录

session处理

SpiderSession()这个类功能是为了处理session:

  1. 初始化
    1. 定义cookie目录
    2. 从配置文件获取user-agent
    3. 初始化session。
  2. 初始化session
  3. 获取并设置header
  4. 获取user_agent
  5. 获取cookie
  6. 设置cookie
  7. 从本地加载cookie
  8. 保存cookie到本地

session的处理这一段代码不太熟悉,之前没有接触过,下面分析一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def _init_session(self):
# 实例化对象
session = requests.session()
# 给 requests.session() 对象设置header信息
session.headers = self.get_headers()
return session

def get_headers(self):
return {"User-Agent": self.user_agent,
"Accept": "text/html,application/xhtml+xml,application/xml;"
"q=0.9,image/webp,image/apng,*/*;"
"q=0.8,application/signed-exchange;"
"v=b3",
"Connection": "keep-alive"}
------ 本文结束 ------

版权声明

Medivh's Notes by Medivh is licensed under a Creative Commons BY-NC-ND 4.0 International License.
Medivh创作并维护的Medivh's Notes博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Medivh 博客( http://www.mknight.cn ),版权所有,侵权必究。