10.24-10.28周末回顾
一、购物车
import os import json "构建记录用户登录的字典" is_login = {'username': ''} "由于都用到了这部分代码,可以将其放在全局中使用" # 4 获取用户名文件路径 base_path = os.path.dirname(__file__) db_path = os.path.join(base_path, 'db') # 5 如果没有db文件路径,则创建 if not os.path.exists(db_path): os.mkdir(db_path) "校验用户登录状态的装饰器" def login_auth(func_name): def inner(*args, **kwargs): # 执行函数前增加的新功能 if not is_login.get('username'): print('您未登录,请先登录') login() res = func_name(*args, **kwargs) return res return inner def register(): # 3 添加循环 while True: # 1 获取用户输入 username = input('请输入用户名:').strip() if username == 'q': break password = input('请输入密码:').strip() confirm_pwd = input('请确认密码:').strip() # 2 判断密码是否正确 if not password == confirm_pwd: print('您的密码不一致,重新输入') continue # 6 拼接用户文件路径 user_file_path = os.path.join(db_path, f'{username}.json') # 7 判断用户文件路径是否存在 if os.path.exists(user_file_path): print('该用户名已经被注册过') continue # 8 不存在则新建用户文件 user_data_dict = { 'username': username, 'password': password, 'balance': 133333, 'shop_car': {} } with open(user_file_path, 'w', encoding='utf8') as f: json.dump(user_data_dict, f) print(f'用户{username}您好,您已经注册成功') break def login(): while True: # 1 获取用户输入 username = input('请输入用户名:').strip() if username == 'q': break # 2 获取用户文件路径,判断路径是否存在 user_file_path = os.path.join(db_path, f'{username}.json') # 3 判断用户名文件是否存在,不存在则未注册 if not os.path.exists(user_file_path): print('您的用户名未注册') continue password = input('请输入您的密码:').strip() # 4 获取用户真实字典 with open(user_file_path, 'r', encoding='utf8') as f: user_data_dict = json.load(f) if not password == user_data_dict.get('password'): print('密码错误,重新输入') continue # 5 登录成功,记录登录的状态,在全局中建立登录状态字典 is_login['username'] = username print(f'用户{username}您好登录成功') break """ 使用3、4功能要判断用户登录状态, 可以构建装饰器,来为3、4功能函数增加判断是否登录的功能 """ @login_auth def add_shop_car(): # 8 构建临时小字典,存放添加的商品信息 temp_good_list = {} while True: # 1 获取商品信息,循环打印输出给用户 good_list = [ ['kfc', 3], ['芦笋烤鹅肝', 22], ['酸奶', 666], ['抹茶拿铁', 999], ['战斧牛排', 1000], ['仰望星空派', 2000], ['鸡哥陪玩', 10000] ] for num, g_data in enumerate(good_list): print(f"商品编号:{num} | 商品名称:{g_data[0]} | 商品单价:{g_data[1]}") # 2 获取用户输入,想要的商品编号 choice_good_num = input('请输入您想要的商品编号:').strip() "10 获取结束条件,保存商品信息" if choice_good_num == 'q': # 11 获取真实用户字典 user_file_path = os.path.join(db_path, f'{is_login.get("username")}.json') with open(user_file_path, 'r', encoding='utf8') as f: user_data_dict = json.load(f) # 12 获取旧购物车 old_shop_car = user_data_dict.get('shop_car') # 13 循环获得原购物车中的商品信息 for g_name, g_list in temp_good_list.items(): if g_name in old_shop_car: old_shop_car[g_name][0] += temp_good_list[g_name][0] else: old_shop_car[g_name] = g_list # 14 将改过的购物车写入用户文件 user_data_dict['shop_car'] = old_shop_car with open(user_file_path, 'w', encoding='utf8') as f: json.dump(user_data_dict, f) print('添加商品成功') break # 3 判断商品编号是否是纯数字 if not choice_good_num.isdigit(): print('商品编号必须是纯数字') continue # 4 判断输入编号是否在商品编号内 choice_good_num = int(choice_good_num) if choice_good_num not in range(len(good_list)): print('您输入的编号不存在') continue # 5 获取此时商品的信息 now_good_list = good_list[choice_good_num] # ['仰望星空派', 2000] # 6 获取商品数量 good_num = input('请输入商品数量:').strip() # 7 判断商品数量是否是纯数字 if not good_num.isdigit(): print('商品数量必须是纯数字') continue good_num = int(good_num) # 9 判断商品名字是否在临时小字典内 good_name = now_good_list[0] # ['仰望星空派', 2000] if good_name in temp_good_list: # temp_good_list ={'仰望星空派': [11, 2000]} temp_good_list[good_name][0] += good_num else: temp_good_list[good_name] = [good_num, now_good_list[1]] @login_auth def pay_shop_car(): # 1 获取用户文件内的信息 user_file_path = os.path.join(db_path, f'{is_login.get("username")}.json') # 2 读取用户文件信息 with open(user_file_path, 'r', encoding='utf8') as f: user_data_dict = json.load(f) # 3 获取真实购物车 shop_car = user_data_dict.get('shop_car') # 4 判断购物车是否为空 if not shop_car: print('您的购物车为空,请先添加商品') return # 5 统计价格 total_money = 0 for g_list in shop_car.values(): total_money += g_list[0] * g_list[1] # 6 获取当前余额 curreent_balance = user_data_dict.get('balance') # 7 判断余额和总价 if total_money > curreent_balance: print('余额不足,请先充值') return user_data_dict['balance'] -= total_money # 8 清空购物车 user_data_dict['shop_car'] = {} # 9 写入文件 with open(user_file_path, 'w', encoding='utf8') as f: json.dump(user_data_dict, f) print(f'用户{is_login.get("username")}结算成功,消费{total_money},余额为{user_data_dict.get("balance")}') # 记录功能编号的字典 func_num_dict = { '1': register, '2': login, '3': add_shop_car, '4': pay_shop_car } # 循环获取字典,调用函数功能 while True: print(""" 1:注册功能 2:登陆功能 3:添加购物车功能 4:结算购物车功能 """) choice_func_num = input('请输入想使用的功能编号:').strip() if choice_func_num not in func_num_dict: print('您选择的功能编号不存在,重新输入') else: func_num_dict.get(choice_func_num)()
二、hashlib模块
hashlib模块中含有很多的加密算法,可以将不同的明文数据通过不同的算法转换成不同的长度的密文,通常以16进制的字符串来表示加密后的密文。
1.加密的含义,如何理解加密
当一串字符我们无法看懂,其中又包括了数字、字母、符号的时候,就有可能是加密处理后的密文。加密的操作可以保证数据的安全,防止数据泄露后造成损失。
关于密文,相同的明文再加密后如果其密文结果越长,就说明其算法越复杂,其安全性也越高。
2.常见的加密算法
md5、 base64、hmac、sha系列等等
2.加密算法的基本使用
三步:1)选择加密算法
2)传入明文数据
3)获取加密密文
# 案例 import hashlib # 导入hashlib加密模块 1.选择加密算法 x = hashlib.md5() # 选择加密算法为md5 2.传入明文数据 1)一次传入明文 # 用update关键字传入明文,选择解码模式是 utf8 x.update('你好我好大家好,广州好迪'.encode(encoding='utf8')) 2)多次传入相同明文 x1.update('你好我好大家好'.encode('utf8')) x1.update(','.encode('utf8')) x1.update('广州好迪'.encode('utf8')) 3)获取加密密文 res = x.hexdigest() # 用关键字hexdigest获取密文,并用一个变量名接收返回的结果 print(res) # d7ceedfa09a76805da2a2830a1764360 res1 = x1.hexdigest() print(res1) # d7ceedfa09a76805da2a2830a1764360 "只要选择的算法相同,传入相同的明文,加密后的结果也是相同的"
3.加密补充说明
1.加密算法不变如果传入的明文相同,加密后的密文也想相同
2.加密之后的结果是无法反解密的
一般所谓的解密都是通过撞库来进行所谓的返解密的,并非破解加密算法
3.加盐处理和动态加盐处理
1)加盐处理:在明文中加入固定的干扰项,使得传入的明文更加的复杂,增加密文的复杂性,防止撞库而得到明文
import hashlib md5 = hashlib.md5() md5.updata(b'公司干扰项', encoding='utf8') # 添加干扰项,防止明文过于简单 md5.update(b'hello~world~python') res = md5.hexdigest()
2)动态加盐:干扰项是随机变化的,防止干扰项被泄露后用户数据被撞库匹配到明文
动态干扰项常用的有:当前时间、用户名的部分字符...这样使得这些加盐处理之后的密文更加安全,难以撞库匹配
4.加密操作的用处
1 对用户密码加密
2 文件安全性校验
3 文件内容一致性校验
4 大文件校验
5.优秀hash算法的特性
正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。
逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。
输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。即对于任意两个不同的数据块,其hash值相同的可能性极小;对于一个给定的数据块,找到和它hash值相同的数据块极为困难。
三、子进程模块subprocess模块
模拟操作系统,执行命令并获取结果
subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。
import subprocess # Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。 res = subprocess.Popen( # 激活终端 'asdas', # 操作系统要执行的命令 shell=True, # 固定配置 stdin=subprocess.PIPE, # 输入命令 stdout=subprocess.PIPE, # 输出结果 ) print('正确结果', res.stdout.read().decode('gbk')) # 获取操作系统执行命令之后的正确结果 print('错误结果', res.stderr) # 获取操作系统执行命令之后的错误结果
Windows系统的编码默认中文系统是gbk编码
MacOS终端默认情况下字符以UTF-8编码,终端中输入locale查看默认编码
四、logging日志模块
1.如何理解日志
日志可以理解为是记录数据行为的文件,它可以帮助我们来快速定位问题。
2.日志的级别
日志的级别,从上往下重要程度依次提高,日志模块的默认日志等级上warning,低于warning等级的日志信息都不会在终端中显示出来。
1.debug logging.debug('debug message') 2.info logging.info('info message') 3.warning logging.warning('warning message') 4.error logging.error('error message') 5.critical logging.critical('critical message')
3.日志的组成

1.产生日志
logger日志记录器,每个记录器都有一个名称,直接使用logging模块来记录日志时,该模块会默认创建
2.过滤日志
剔除不良品,在日志阶段就可以控制想要的日志内容
3.输出日志
handler处理器,记录器负责产生日志,而处理器则负责日志最终的输出,存放成日志文件。
4.日志格式
formatter格式器,格式器可以以对象的形式设置在handler上,格式器可以指定日志的输出格式,比如展示时间、时间格式、日志的级别、展示记录器的名字等等,都可以通过一个格式器对消息进行格式化输出。
Python内置了很多实用的处理器,常用的有:
1、StreamHandler 标准流处理器,将消息发送到标准输出流、错误流
2、FileHandler 文件处理器,将消息发送到文件
3、RotatingFileHandler 文件处理器,文件达到指定大小后,启用新文件存储日志
4、TimedRotatingFileHandler 文件处理器,日志以特定的时间间隔轮换日志文件
import logging # 1.日志的产生(准备原材料) logger对象 logger = logging.getLogger('购物车记录') # 2.日志的过滤(剔除不良品)基本不用,在日志生产阶段就可以控制想要什么样的日志内容 # 3.日志的输出(成品) handler对象 hd1 = logging.FileHandler('a1.log',encoding='utf8') # 输出到文件中 hd2 = logging.FileHandler('a2.log',encoding='utf8') # 输出到文件中 hd3 = logging.StreamHandler() # 输出到终端 # 4.日志的格式(包装) formatter对象 fm1 = logging.Formatter( fmt='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', ) fm2 = logging.Formatter( fmt='%(asctime)s - %(name)s: %(message)s', datefmt='%Y-%m-%d', ) # 5.给logger对象绑定handler对象 logger.addHandler(hd1) logger.addHandler(hd2) logger.addHandler(hd3) # 6.给handler绑定formmate对象 hd1.setFormatter(fm1) hd2.setFormatter(fm2) hd3.setFormatter(fm1) # 7.设置日志等级 logger.setLevel(10) # debug 20-info 30-warning 40-error 50-critical # 8.记录日志 logger.debug('日志内容日志内容')
五、关于python第三方模块的简介
第三方模块是技术大佬写的模块,功能很多
1.下载第三方模块的方式
1.1 pip工具
注意每个解释器都有pip工具,如果我们的电脑上有多个版本的解释器那么我们在使用pip的时候一定要注意到底用的是哪一个 否则极其任意出现使用的是A版本解释器然后用B版本的pip下载模块
(1) 为了避免pip冲突 我们在使用的时候可以添加对应的版本号,如
python27 pip2.7 python36 pip3.6 python38 pip3.8
(2)下载第三方模块的句式
pip install 模块名
(3)下载第三方模块临时切换仓库
pip install 模块名 -i 仓库地址
(4)下载第三方模块指定版本(不指定默认是最新版)
pip install 模块名==版本号 -i 仓库地址
pip install 模块名==版本号 -i 仓库地址
1.2 pycharm提供的下载方式

2.下载第三方模块可能会出现的问题
1.报错并有警告信息 WARNING: You are using pip version 20.2.1; 原因在于pip版本过低 只需要拷贝后面的命令执行更新操作即可 d:\python38\python.exe -m pip install --upgrade pip 更新完成后再次执行下载第三方模块的命令即可 2.报错并含有Timeout关键字 说明当前计算机网络不稳定 只需要换网或者重新执行几次即可 3.报错并没有关键字 面向百度搜索 pip下载XXX报错:拷贝错误信息 通常都是需要用户提前准备好一些环境才可以顺利下载 4.下载速度很慢 pip默认下载的仓库地址是国外的 python.org 我们可以切换下载的地址为国内的地址 # 命令行操作 pip install 模块名 -i 仓库地址 """常用的国内仓库地址 清华大学 :https://pypi.tuna.tsinghua.edu.cn/simple/ 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科学技术大学 :http://pypi.mirrors.ustc.edu.cn/simple/ 华中科技大学:http://pypi.hustunique.com/ 豆瓣源:http://pypi.douban.com/simple/ 腾讯源:http://mirrors.cloud.tencent.com/pypi/simple 华为镜像源:https://repo.huaweicloud.com/repository/pypi/simple/"""
六、requests模块-网络爬虫模块
1.小练习:获取宏牛网站的分公司信息
# 思路 1.直接拷贝网友源代码数据保存到本地 2.在pycharm中读取文件当作字符串处理 3.编写正则表达式来筛选我们想要的内容 import re # 1.文件操作读取文本内容 with open(r'redbull.html', 'r', encoding='utf8') as f: # 2 直接读取全部内,将全部内容绑定变量名data data = f.read() # 3 研究各部分数据的特征,编写相应的正则表达式 # <h2>红牛杭州分公司</h2><p class='mapIco'>杭州市上城区庆春路29号远洋大厦11楼A座</p><p class='mailIco'>310009</p><p class='telIco'>0571-87045279/7792</p></li><li "方法1:一次性获取每个公司全部的数据" # res = re.findall( # "<h2>(.*?)</h2><p class='mapIco'>(.*?)</p><p class='mailIco'>(.*?)</p><p class='telIco'>(.*?)</p></li><li", data) # # print(res) "方法2:分步分挨个获取最后统一整合" title_list = re.findall("<h2>(.*?)</h2>", data) # print(title_list) """ ['红牛杭州分公司', ... ,'红牛金丽衢代表处'] """ address_list = re.findall("<p class='mapIco'>(.*?)</p>", data) mail_list = re.findall("<p class='mailIco'>(.*?)</p>", data) telephone_list = re.findall("<p class='telIco'>(.*?)</p>", data) # 4 (处理信息)得到了公司名称、公司地址、公司邮编、公司电话这些信息的列表后,我们需要将其一一对应起来组合 res = zip(telephone_list, address_list, mail_list, telephone_list) # print(list(res)) # [('0571-87045279/7792', '杭州市上城区庆春路29号远洋大厦11楼A座', '310009', '0571-87045279/7792')...] # 5 将其写入txt文件中 with open(r'redbull.txt', 'w', encoding='utf8') as f: # 6 添加for循环,可以格式化输出 for data_tuple in res: print( """ 公司名称:%s 公司地址:%s 公司邮编:%s 公司电话:%s """ % data_tuple) f.write( """ 公司名称:%s 公司地址:%s 公司邮编:%s 公司电话:%s """ % data_tuple)
2.requests模块简介
requests模块能够模拟浏览器发送网络请求 # Python 内置了 requests 模块,该模块主要用来发 送 HTTP 请求 1.requests模块的语法 # 1 导入 requests 包 import requests # 2 发送请求 # 朝指定网址发送请求获取页面数据(等价于:浏览器地址栏输入网址回车访问) x = requests.get('http://www.redbull.com.cn/about/branch') # 3 返回网页内容 print(x.text) # 并非所有网站都是以utf8来进行字符编码的 2.requests模块语法的补充说明 # 1 获取bytes类型的网页数据(二进制) print(x.content) # 2 可以指定字符编号,已经获取bytes类型的网页数据(二进制) x.encoding = 'utf8' # 指定编码 print(x.text) # 获取字符串类型的网页数据(默认按照utf8)
3.小练习:利用requests模块来获取莲家二手房的二手房数据
""" 思路: 1.通过requests模块模拟浏览器向链家网站发送请求 2.返回网页内容 3.研究网页上的内容,编写对应的正则表达式 4.筛选出结果写入文件中 """ import requests import re # 链家网站:https://sh.lianjia.com/ershoufang/pudong/ # 1 通过requests模块获取链家网站的内容 web_lj = requests.get('https://sh.lianjia.com/ershoufang/pudong/') # 2 返回内容 data = web_lj.text # 3 通过正则表达式来匹配数据,匹配我们想要的结果 house_title_list = re.findall( 'data-is_focus="" data-sl="">(.*?)</a>', data) print(house_title_list) house_position_list = re.findall('<a href=".*?" target="_blank" data-log_index=".*?" data-el="region">(.*?)</a>', data) # print(house_position_list) house_street_list = re.findall('- <a href=".*?" target="_blank">(.*?)</a>', data) # print(house_street_list) house_info_list = re.findall('<div class="houseInfo"><span class="houseIcon"></span>(.*?)</div>', data) house_follow_list = re.findall('<div class="followInfo"><span class="starIcon"></span>(.*?)</div>', data) house_total_price_list = re.findall( '<div class="totalPrice totalPrice2"><i> </i><span class="">(.*?)</span><i>万</i></div>', data) house_unit_price_list = re.findall( '<div class="unitPrice" data-hid=".*?" data-rid=".*?" data-price=".*?"><span>(.*?)</span></div>', data) house_data = zip(house_title_list, house_position_list, house_street_list, house_info_list, house_follow_list, house_total_price_list, house_unit_price_list) # 4 创建文件保存数据 with open(r'sec_hand_house.txt','w',encoding='utf8') as f: for data in house_data: print(""" 房屋标题:%s 小区名称:%s 街道名称:%s 详细信息:%s 关注程度:%s 房屋总价:%s万元 房屋单价:%s """ % data ) f.write(""" 房屋标题:%s 小区名称:%s 街道名称:%s 详细信息:%s 关注程度:%s 房屋总价:%s万元 房屋单价:%s """ % data )
七、openpyxl模块-自动化办公
1.openpyxl模块简介
1.excel文件的后缀名问题 2003版本之前后缀名为: ` .xls` 2003版本之后后缀名为: ` .xlsx` 2.操作excel表格的第三方模块 1)`xlwt`往表格中写入数据(兼容所有版本的excel文件) 2)`wlrd`从表格中读取数据(兼容所有版本的excel文件) 3)**`openpyxl`最近几年比较火热的操作excel表格的模块(对2003版本之前的兼容性较差 )
2.openpyxl操作
很多模块都会有官方文档,可以帮助我们快速了解如何使用该模块
openpyxl中的对象Workbook
- 1 workbook 相当于一个 Excel 文件档,每个被创建和打开的 Excel 文件都是独立的 Workbook 对象
- 2 sheet Excel 文档中的表单,每个 Excel 文档至少需要一个 sheet
- 3 cell 单元格,是不可分割的基本数据存储单元
from openpyxl import Workbook 1.创建一个excel文件 `Workbook`关键字 wb = Workbook() 2.在一个excel文件内创建多个工作簿sheet `create_sheet` wb1 = wb.create_sheet('宿舍名单') wb2 = wb.create_sheet('身份证信息') wb3 = wb.create_sheet('电话信息') 3.修改默认的工作簿位置 # 在想修改的工作簿添加索引参数 wb4 = wb.create_sheet('女朋友电话', 0) 4.二次修改工作簿名称 `工作簿名.title = '新命名'` wb4.title = '男神电话' wb4.sheet_properties.tabColor = "1072BA" 5.填写数据 1)wb4['A1'] = 'haha' 2)wb4.cell(row=3, column=1, value='jason') 3)类似表格的形式直接写入数据 wb4.append(['编号', '姓名', '年龄', '爱好']) # 表头字段 wb4.append([1, 'jason', 18, 'read']) wb4.append([2, 'kevin', 28, 'music']) wb4.append([3, 'tony', 58, 'play']) wb4.append([4, 'oscar', 38, 'ball']) wb4.append([5, 'jerry', 'ball']) wb4.append([6, 'tom', 88,'ball','哈哈哈']) 6.填写数据额公式 # 默认是公式本身,不会出现结果,需要用value参数指定才会获取计算结果 wb4['A5'] = '=sum(A1:A4)' wb4.cell(row=8, column=3, value='=sum(A1:A4)') 7.保存excel文件 wb.save(r'aaaa.xlsx')
-
excel软件正常可以打开操作的数据集数量在10万左右, 一旦数据集过大,软件操作几乎无效需要使用pandas模块进行代码操作
-
模块openpyxl 主要用于数据的写入
-
模块pandas 擅长表单操作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY