python学习Day28

Day 28

今日内容概要

  • openpyxl模块
    • openpyxl模块读数据
  • 封装了openpyxl的pandas模块操作excel表格的方式
  • 网络爬虫实操—爬取链家二手房数据(更方便)
  • random随机数模块
  • hashlib加密模块
  • subprocess远程命令模块
  • logging日志模块
    • 日志模块详细组成部分
    • 日志配置字典
    • 实战应用

今日内容详细

1.openpyxl模块读取数据
1.openpyxl读写分离(写与读是两个不同模块) 需在后面加逗号load_workbook
    #调用openpyxl模块的读写模块
    from openpyxl import Workbook,load_workbook

    wb=Workbook()#创建一个excel文件
    wb1=wb.create_sheet('第一个sheet页',0)#创建一个sheet页并放在第一个位置上
    wb2=wb.create_sheet('第二个sheet页',1)#创建一个sheet页并放在第二个位置上
    wb1.append(['username','gender','age'])#批量方式写入数据
    wb1.append(['jason','male','18'])#批量方式写入数据
    wb.save(r'练习excel.xlsx')#保存文件在该路径下,并起名字

    print(wb.sheetnames)#查看excel文件中所有工作簿名称 ['第一个sheet页','第二个sheet页','Sheet']

    print(wb1.max_row)#查看该工作簿中有几行数据 2(空数据默认显示1)
    print(wb1.max_column)#查看该工作簿中有几列数据 3(空数据默认显示1)
    
    print(wb1['A1'].value)#读取wb1 'A1'单元格的数据username
    print(wb1.cell(row=2,column=1).value)#读取wb1 第二行第一列的数据
    
    #读取整行的数据
    for i in wb1.rows:
        # print(i)#(<Cell'第一个sheet页'.A1>, <Cell'第一个sheet页'.B1>, <Cell'第一个sheet页'.C1>)
        print([j.value for j in i])#['username','gender','age']
    #读取整列的数据
    for j in wb1.columns:
        print([i.value for i in j])#['username','jason','cat']
  '''
  openpyxl不擅长读数据,所以有一些模块优化了读取的方式:pandas模块
  一般在公司会有专门的人负责读,python程序员只负责写出来
  '''
2.封装了openpyxl的pandas模块操作excel表格的方式
#封装了openpyxl的pandas模块操作excel表格的方式:
底层实际还是用了openpyxl,仅是模块的互相叠加处理

import pandas
d={
    '公司名称':['老男孩','老女孩','老北鼻'],
    '公司地址':['上海','深圳','杭州'],
    '公司电话':['111','222','333'],
}
df=pandas.DataFrame(d)
df.to_excel(r'练习excel.xlsx')

image

3.网络爬虫实操—爬取链家二手房数据
爬取链家二手房信息(抽时间试试爬多页,还有其他更快捷的方法)

import re
import requests
import pandas

# res=requests.get('https://sh.lianjia.com/ershoufang/')#朝该地址发送获取数据请求
#只能获取一页的数据
#把该地址这一页保存起来(防止获取数据多了被网站封ip)
# with open(r'lj.html','wb')as f:
    # f.write(res.content)#写入二进制

#用r模式读取页面字符串数据
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)
#2.获取小区名称
home_name_list=re.findall('<a href=".*?" target="_blank" data-log_index=".*?" data-el="region">(.*?) </a>',data)

#构造一个大字典存放信息
d={'房屋名称':home_title_list,
   '小区名称':home_name_list}
df=pandas.DataFrame(d)
df.to_excel(r'房屋信息.xlsx')


4.random随机数模块
import random

#返回0~1之间随机的小数
	print(random.random())
#返回1~6之间随机的小数(包含1和6)
	print(random.randint(1,6))
#随机抽一个数据
	print(random.choice(['一等奖','二等奖','谢谢惠顾']))
#随机抽两个数据
	print(random.sample(['张三','李四','王五','jason'],2))
#随机打乱顺序(洗牌)
	l1=[1,2,3,4,5,6]
	random.shuffle(l1)
	print(l1)
搜狗python工程师笔试题:
eg:编写python代码,产生五位随机验证码(数字、大小写字母)
    
import random
code=''#创建一个全局变量用来存储随机验证码信息,让code等于一个空字符串,然后字符串拼接
#需要5位数就循环5次
for i in range(5):
    #每次循环都应该产生一个数字或大小写字母
    random_int=str(random.randint(0,9))#数字和字符串不可以兼容,为了拼接需转换成字符串
    random_lower=chr(random.randint(97,122))#chr数字转字母  97~122=a~z
    random_upper=chr(random.randint(65,90))#chr数字转字母  65~90=A~Z
    #从上述三个数据中随机挑选一个作为验证码最后以为
    temp=random.choice([random_int,random_lower,random_upper])
    #拼接for循环到的随机数
    code += temp
print(code)
5.hashlib加密模块
1.什么是加密?
	将明文数据经过处理后变成密文数据的过程
2.为什么要加密?
	不想让敏感数据轻易泄露
3.如何判断当前数据是否已加密?
	一般如果是一串没有规则的字母、数字组合的就是加密后的结果
4.加密算法就是对明文数据采用的加密策略
    不同的加密算法复杂度不一样,得出的结果长短也不一样
	通常加密后长度越长,说明采用的加密算法越复杂
5.常见的加密算法
	md5   sha系列   hmac   base64
6.代码实操
    import hashlib
    md5=hashlib.md5()#选择md5加密算法作为数据的加密策略
    md5.update(b'123')#往里面添加明文数据 数据必须是bytes类型
    res=md5.hexdigest()#获取加密后的结果
    print(res)#202cb962ac59075b964b07152d234b70
加密模块其他说明:

1.加密之后的结果一般情况下不能反解密
	所谓的反解密其实就是提前假设你的密码是什么,然后用各种算法算出对应的密文,然后构造对应的关系再比对密文,最终得出明文 #举例: {'密文1':123,'密文2':321,...}
    
2.只要明文数据一样,那么采用相同算法得出的密文肯定一样
     只要明文一样,不管分几次加密,最后都和一次的结果一样
    #加密分三次
    import hashlib
    md5 = hashlib.md5() # 选择md5加密算法作为数据的加密策略
    md5.update(b'123') # 往里面添加明文数据 数据必须是bytes类型
    md5.update(b'hello') # 往里面添加明文数据 数据必须是bytes类型
    md5.update(b'jason') # 往里面添加明文数据 数据必须是bytes类型
    res = md5.hexdigest() # 获取加密后的结果
    print(res) # 31b9a81dc788368469ee4b78877eb1eb
    
    #加密分一次
    import hashlib
    md5 = hashlib.md5() # 选择md5加密算法作为数据的加密策略
    md5.update(b'123hellojason') # 往里面添加明文数据 数据必须是bytes类型
    res = md5.hexdigest() # 获取加密后的结果
    print(res) # 31b9a81dc788368469ee4b78877eb1eb
    
3.加盐处理(salt)在用户真实明文数据前加一个数据作为干扰项,好让加密结果更复杂
    import hashlib
    md5=hashlib.md5() # 选择md5加密算法作为数据的加密策略
    pwd = input('pwd>>>:').strip()
    md5.update('干扰项'.encode('utf8')) #转为bytes类型
    md5.update(pwd.encode('utf8')) #转为bytes类型
    res = md5.hexdigest() # 获取加密后的结果
    print(res)
    
4.动态加盐
	干扰项每次都不一样,一般是每次获取当前时间、用户名截取一段等

5.加密实际应用场景
	1)用户密码加密
    	注册存储的是密文,登录也是在对比密文
	2)文件安全性校验
    	正规的软件程序写完会做一个内容加密
          eg: 网站会提供软件文件以及该文件内容对应的密文,用户下载完成后不直接运行而是对下载的内容做加密,然后对比两次密文是否一致,如果不一致则表示该软件可能被植入了病毒
	3)大文件加密优化策略
    	有一个程序文件100G
            一般情况下读取100G内容然后全部加密,效率太低很慢
            可以采用切分不全部加密,截取一部分来加密(比如每500M读取30bytes)
          'os模块中有个 os.path.getsize()可以获取文件有多大,然后自行制订切多少'
6.subprocess远程命令模块
模拟计算机cmd命令窗口
    import subprocess

    cmd=input('输入cmd指令:').strip()
    sub=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    #stdout执行命令正确之后的返回结果
    print(sub.stdout.read().decode('gbk'))#正确结果
    #stdout执行命令报错之后的返回结果
    print(sub.stderr.read().decode('gbk'))#不是内部或外部命令,也不是可运行的程序
7.logging日志模块
日志模块需要写的代码很少 几乎都是cv

1.什么是日志?
	日志就是类似于历史记录
2.为什么要用日志
	为了记录事物发生的事实(史官)
3.如何使用日志
  1)日志等级
    import logging
    logging.debug('debug等级')#10 默认不显示
    logging.info('info等级')#20 默认不显示
    logging.warning('警告的')#30 默认从warning级别开始记录
    logging.error('已经发生的')#40
    logging.critical('灾难性的')#50
  2)基本使用
#在那个文件执行,就会在记录日志文件中记录该文件的日志
    import logging
    #产生一个日志文件,文件叫x1.log,用a追加模式,编码为utf8
    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',
        #用handler
        handlers=[file_handler,],
        #ERROR级别
        level=logging.ERROR
    )

    logging.error('我不好!!!')
8.日志模块详细组成部分

在记录日志时,不需要和下面一样全自己写,该模块提供了固定的配置字典,可以直接调用,下面仅是了解即可

1.日志模块要想产生使用,分为4个阶段
  1)日志的产生(准备原材料)    logger对象  使用前的准备
  2)日志的过滤(剔除不良品)	filter对象  可以忽略不使用,第一步就可以完成
    logger = logging.getLogger('购物车记录')#产生一个日志
    
  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',)
2.给logger对象绑定handler对象
    logger.addHandler(hd1)
    logger.addHandler(hd2)
    logger.addHandler(hd3)
3.给handler绑定formmate对象
    hd1.setFormatter(fm1)
    hd2.setFormatter(fm2)
    hd3.setFormatter(fm1)
4.设置日志等级
    logger.setLevel(10)  # 10对应debug,所有等级都显示
5.记录日志
	logger.debug('写了半天 好累啊 好热啊')
9.日志配置字典
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('慢男 猛男 骚男')
10.日志模块实战应用
# 按照软件开发目录规范编写使用
日志字典数据应该放在哪个py文件内
	字典数据是日志模块固定的配置 写完一次之后几乎都不需要动
  它属于配置文件
  """配置文件中变量名推荐全大写"""
该案例能够带你搞明白软件开发目录规范中所有py文件的真正作用

def get_logger(msg):
    # 记录日志
    logging.config.dictConfig(settings.LOGGING_DIC)  # 自动加载字典中的配置
    logger1 = logging.getLogger(msg)
    # logger1.debug(f'{username}注册成功')  # 这里让用户自己写更好
    return logger1

作业

1.整理今日内容及博客
2.思考链家二手房多页数据如何爬取
3.完善购物车程序
	尝试拆封成软件开发目录规范
	添加记录日志功能
posted @ 2022-07-21 23:01  逢诱  阅读(41)  评论(0)    收藏  举报