openpyxl模块、random模块、hashilb模块、subprocess、日志模块
一、openpyxl模块读数据
openpyxl读写数据使用的模块不一样
读的模块:from openpyxl import Workbook
from openpyxl import Workbook
wb = Workbook()
wb1 = wb.create_sheet('花名册')
wb2 = wb.create_sheet('成绩表')
wb3 = wb.create_sheet('获奖名单')
wb1.append(['username', 'gender', 'age'])
wb1.append(['jason', 'male', '38'])
wb1.append(['kevin', 'male', '28'])
wb1.append(['tony', 'meal', '18'])
wb1['C5'] = '=sum(C2:C4)'
wb.save(r'111.xlsx')
写的模块:from openpyxl import load_workbook
wb = load_workbook(r'111.xlsx',data_only=True)
print(wb.sheetnames) # 查看excel文件中所有的工作簿名称 ['花名册', 'Sheet', '成绩表', '获奖名单']
wb1 = wb['花名册']
print(wb1.max_row) # 当前工作簿最多有5行
print(wb1.max_column) # 当前工作簿最多有5列
print(wb1['A1'].value) # 会拿到A1单元格里的数据
print(wb1.cell(row=2,column=2).value) # 第二种取值方式
for i in wb1.rows:
print([j.value for j in i]) # 列表生成式
for j in wb1.columns:
print([i.value for i in j])
pandas模块读数据
openpyxl不擅长读数据 所以有一些模块优化了读取的方式,例如pandas模块,它的底层用的是openpyxl
import pandas
d = {
'公司名称': ['老男孩', '老女孩', '老伙计', '老北鼻'],
'公司地址': ['上海', '深圳', '杭州', '东京'],
'公司电话': [120, 130, 129, 996],
}
df = pandas.DataFrame(d)
df.to_excel(r'222.xlsx')
二、爬取链家二手房数据
封装了openpyxl的pandas模块操作excel表格的方式
将有独特标识的全部去掉换成 .*?,没有加(),说明所在的地方的内容不要
import pandas
import requests
with open(r'lj.html', 'r', encoding='utf8') as f:
data = f.read()
# 1.研究目标数据 筛选
home_title_list = re.findall(
'<a class="" href=".*?" target="_blank" data-log_index=".*?" data-el="ershoufang" data-housecode=".*?" data-is_focus="" data-sl="">(.*?)</a>',
data
)
home_name_list = re.findall(
'<a href=".*?" target="_blank" data-log_index=".*?" data-el="region">(.*?) </a>',
data
)
home_addr_list = re.findall(
' - <a href=".*?" target="_blank">(.*?)</a>',
data
)
home_info_list = re.findall(
'<div class="houseInfo"><span class="houseIcon"></span>(.*?)</div>',
data
)
home_others_list = re.findall(
'<div class="followInfo"><span class="starIcon"></span>(.*?)</div>',
data
)
home_total_price = re.findall(
'<div class="totalPrice totalPrice2"><i> </i><span class="">(.*?)</span><i>万</i></div>',
data
)
home_unit_price = re.findall(
'<div class="unitPrice" data-hid=".*?" data-rid=".*?" data-price=".*?"><span>(.*?)</span></div>',
data
)
d = {
'房屋标题': home_title_list,
'小区名称': home_name_list,
'所在街道': home_addr_list,
'具体信息': home_info_list,
'其他信息': home_others_list,
'房屋总价': home_total_price,
'房屋单价': home_unit_price
}
df = pandas.DataFrame(d)
df.to_excel(r'333.xlsx')
三、random随机数模块
1.random.random() 返回0到1之间随机的小数
import random
# 返回0到1之间随机的小数 0.6775606052707718
print(random.random())
2.random.randint(a, b) 返回a到b之间随机的整数
# 返回1到6之间随机的整数 掷骰子
print(random.randint(1, 6))
3.random.choice() 随机抽取一个
# 随机抽取一个
print(random.choice(['一等奖', '特等奖', '谢谢惠顾', '如花抱回家']))
4.random.sample(a, num) 随机抽样 自定义抽取个数
# 随机抽样 自定义抽取个数
print(random.sample(['慢男', '快男', '猛男', '老六', '老七', '男男', '老八秘制小汉堡'], 3))
5.random.shuffle() 随机的做一个打乱
l1 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A', '大王', '小王']
random.shuffle(l1)
print(l1) # [3, '小王', 'Q', 6, 7, 2, 9, 5, 'K', 10, 8, '大王', 'J', 'A', 4]
-搜狗python工程师笔试题
def get_code(n):
code = '' # 定义全局变量用于存储所有的验证码
# 编写python代码 产生五位随机验证码(数字、小写字母、大写字母)
for i in range(n): # range里面的数字控制着产生几位验证码
# 每次循环都应该产生 数字 小写字母 大写字母
random_int = str(random.randint(0, 9)) # 随机产生一个数字
random_lower = chr(random.randint(97, 122)) # 随机产生一个小写字母
random_upper = chr(random.randint(65, 90)) # 随机产生一个大写字母
# 从上述三个数据值中随机挑选一个作为验证码的一位数据
temp = random.choice([random_int, random_lower, random_upper])
code += temp # 拼接字符串
return code
# 产生自己想要的验证码数
res = get_code(4)
res1 = get_code(6)
四、hashilb加密模块
1.什么是加密
将明文数据经过处理之后变成密文数据的过程,由看得懂----->看不懂
2.为什么要加密
将明文数据通过一些特殊的方式处理成一些不规则的数据,不想让敏感的数据轻易的泄露
3.如何判断当前数据值是否已经加密
一般情况下如果是一串没有规则的数字字母符合的组合一般都是加密之后的结果
4.加密后并不是信息完全安全
所有发送出去的请求其实是可以被拦截下来的
5.加密算法
不同的加密算法复杂度不一样,得出的结果长短也不一样
通常情况下加密之后的结果越长,说明采用的加密算法越复杂
6.常见加密算法
md5、sha系列、 hmac、 base64
7.实际操作--md5算法
import hashlib
# 选择md5加密算法作为数据的加密策略
md5 = hashlib.md5()
# 往里面添加明文数据 数据必须是bytes类型
md5.update(b'12234567890')
# 获取加密之后的结果
res = md5.hexdigest()
print(res) # 263c5acd2d38b1fc14e17cb42a329a74
五、加密模块补充说明
1.加密之后的结果一般情况下不能反解密
很多算法是不能反推回去,人们常说的反解其实是偷换了概念,提前假设别人的密码是什么,然后用各种算法算出对应的密文,之后构造对应关系,然后比对密文,最终映射明文
2.只要明文数据是一样的那么采用相同的算法得出的密文肯定一样
import hashlib
md5 = hashlib.md5()
md5.update(b'123abc')
res = md5.hexdigest()
print(res) # a906449d5769fa7361d7ecc6aa3f6d28
'''不论是分开处理还是一次性处理,她的密文都是一样的'''
md5.update(b'123')
md5.update(b'abc')
res1 = md5.hexdigest()
print(res1) # a906449d5769fa7361d7ecc6aa3f6d28
3.加盐处理(salt)
import hashlib
md5 = hashlib.md5()
md5.update(b'123abc')
password = input('password>>>:').strip()
md5.update('盐'.encode('utf8'))
res = md5.hexdigest()
print(res) # 7d2965c2263fd1f057c8965084a41cda
4.动态加盐(salt)
干扰项每一次都有不一样
5.加密实际应用场景
5.1用户密码加密:获取到明文密码之后,给用户的明文密码做加密处理,然后将加密过后的明文密码放到用户数据里,登录的时候,先拿到密文,然后用当初拿到的相同策略去拿到一个密文,然后与用户这里的密文进行比对,查看是否一致
5.2文件安全性校验:正规的软件程序写完之后做一个内容的加密,然后比对俩次密文是否一致,如果一致表示文件没有被改,不一致则表示改程序有可能被植入病毒
5.3大文件加密优化:程序文件100G,一般情况下读取100G内容然后全部加密太慢,采用切割的方法,不对100G所有的内容加密 而是截取一部分加密
六、subprocess模块
用途:模拟计算机cmd命令窗口
# 模拟了cmd终端
import subprocess
cmd = input('请输入您的指令>>>:')
sub = subprocess.Popen('ipconfig',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# print(sub.stdout.read()) # 结果是bytes类型
# stdout执行命令之后正确的返回结果
print(sub.stdout.read().decode('gbk')) # 结果是bytes类型
# stderr执行命令报错之后的返回结果
print(sub.stderr.read().decode('gbk'))
七、日志模块
1.什么是日志
日志就类似于是历史记录
2.为什么要使用日志
为了记录事物发生的事实(历史记录)
3.如何使用日志
3.1.日志等级
import logging
logging.debug('debug等级')
logging.info('info等级')
logging.warning('warning等级') # 默认从warning级别开始记录日志
logging.error('error等级')
logging.critical('critical等级')
3.2.基本使用
import logging
file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8', )
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers=[file_handler, ],
level=logging.ERROR
)
logging.error('错了错了错了')
八、日志模块组成部分
过程 | 使用的对象 |
---|---|
日志的产生 | logger对象 |
日志的过滤 | filter对象 |
日志的产出 | handler对象 |
日志的格式 | format对象 |
import logging
# 1.日志的产生(准备原材料) logger对象
logger = logging.getLogger('购物车记录')
# 2.日志的过滤(剔除不良品) filter对象>>>:可以忽略 不用使用
# 3.日志的产出(成品) handler对象
hd1 = logging.FileHandler('a1.log', encoding='utf-8') # 输出到文件中
hd2 = logging.FileHandler('a2.log', encoding='utf-8') # 输出到文件中
hd3 = logging.StreamHandler() # 输出到终端
# 4.日志的格式(包装) format对象
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
# 8.记录日志
logger.debug('日志记录')
九、日志配置字典
import logging
import logging.config
# 定义日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
# 自定义文件路径
logfile_path = 'a3.log'
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {}, # 过滤日志
'handlers': {
#打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
#打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': logfile_path, # 日志文件
'maxBytes': 1024*1024*5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
#logging.getLogger(__name__)拿到的logger配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
}, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
# '购物车记录': {
# 'handlers': ['default','console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
# 'level': 'WARNING',
# 'propagate': True, # 向上(更高level的logger)传递
# }, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
},
}
logging.config.dictConfig(LOGGING_DIC) # 自动加载字典中的配置
# logger1 = logging.getLogger('购物车记录')
# logger1.warning('尊敬的VIP客户 晚上好 您又来啦')
# logger1 = logging.getLogger('注册记录')
# logger1.debug('jason注册成功')
logger1 = logging.getLogger('红浪漫顾客消费记录')
logger1.debug('慢男 猛男 骚男')
十、实战应用
# 按照软件开发目录规范编写使用
日志字典数据应该放在哪个py文件内
字典数据是日志模块固定的配置 写完一次之后几乎都不需要动
它属于配置文件
"""配置文件中变量名推荐全大写"""
该案例能够带你搞明白软件开发目录规范中所有py文件的真正作用
def get_logger(msg):
# 记录日志
logging.config.dictConfig(settings.LOGGING_DIC) # 自动加载字典中的配置
logger1 = logging.getLogger(msg)
# logger1.debug(f'{username}注册成功') # 这里让用户自己写更好
return logger1