python基础21 第三方 openpyxl,random,hashlib,subprocess, logging 模块

119 阅读8分钟

openpyxl模块读数据

    # openpyxl 读写数据使用的模块不一样
from openpyxl import Workbook, load_workbook

wb = Workbook()
wb1 = wb.create_sheet('cosplay商单价目表')

wb1.append(['username', 'progaram', 'prince'])
wb1.append(['zhewei', 'dance', '500'])
wb1.append(['miki', 'sing', '300'])
wb1.append(['miki', 'sing', '300'])

    # wb.save(r'shoping.xlsx')     # 先保存数据在进行操作
   
   # 读取excel表格
wb = load_workbook(r'shoping.xlsx')
print(wb.sheetnames)         # 查看excal文件中所有的工作簿     结果:['Sheet', 'cosplay商单价目表']
wb1 = wb['cosplay商单价目表']    # 指定工作簿

print(wb1.max_row)               # 显示当前工作簿的最大行数    结果:4    
print(wb1.max_column)            # 显示当前工作簿的最大列数    结果:3

    # 两种单元格取值的方式
print(wb1['A1'].value)                          结果:username
print(wb1.cell(row=1,column=2).value)           结果:progaram

    # 拿到工作簿里面的数据
    # 横着取
for i in wb1.rows:
    print([j.value for j in i])  
             
                    结果:
                    ['username', 'progaram', 'prince']
                    ['zhewei', 'dance', '500']
                    ['miki', 'sing', '300']
                    ['miki', 'sing', '300']       
    
    # 竖着取
for j in wb1.columns:
    print([i.value for i in j])
                   
                   结果:
                   ['username', 'zhewei', 'miki', 'miki']
                   ['progaram', 'dance', 'sing', 'sing']
                   ['prince', '500', '300', '300']


# openpyxl 不擅长读数据,所以所以有一些模块优化了读取的方式
# pandas模块    一层层优化


# 封装了openpyxl的pandas模块操作excel表格的方式
# 导入pandas包的方式:  pacharm直接导入或cmd执行pip install pandas -i 源的地址
import pandas

d = {
    '公司名称': ['老男孩', '老女孩', '老伙计', '老北鼻'],
    '公司地址': ['上海', '深圳', '杭州', '东京'],
    '公司电话': [120, 130, 129, 996],
}
df = pandas.DataFrame(d)
df.to_excel(r'222.xlsx')

                           #也可以对excel表格操作

爬取链家二手房数据

import requests
       # 这样只能获取到一页链家的数据
res = requests.get('https://sh.lianjia.com/ershoufang/')
with open(r'lj.html', 'wb') as f:
     f.write(res.content)
import re
import pandas
               # 这样只能获取到一页链家的数据,
               # res = requests.get('https://sh.lianjia.com/ershoufang/')
               # with open(r'lj.html', 'wb') as f:
               #      f.write(res.content)

      # 读取写入文件的网页信息
with open(r'lj.html', 'r', encoding='utf8') as f:
     data = f.read()
     # print(data, type(data))   # 字符串

      # 研究目标数据,筛选条件    查找,每一类的特点筛选
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
)
                        # print(home_title_list)
                        # 房屋信息
home_name_list = re.findall(
     '<a href=".*?" target="_blank" data-log_index=".*?" data-el="region">(.*?)</a>',data
)

home_address_list = re.findall(
     '<a href=".*?" target="_blank">(.*?)</a> </div></div><div class="address">', data
)

home_info_list = re.findall(
     '<div class="houseInfo"><span class="houseIcon"></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
)
home_others_list = re.findall(
    '<div class="followInfo"><span class="starIcon"></span>(.*?)</div>',
    data
)
d = {
     '房屋标题': home_title_list,
     '小区名称': home_name_list,
     '所在街道': home_address_list,
     '具体信息': home_info_list,
     '其他信息': home_others_list,
     '房屋总价': home_total_price,
     '房屋单价': home_unit_price
}
                 # 将获取的列表保存到链家excel文件
df = pandas.DataFrame(d)
df.to_excel(r'链家.xlsx')

random随机数模块

# 导入random模块
import random
    1. random.random
    • 返回0-1之间的随机小数
      print(random.random())
      
    1. random.randint
    • 返回两个整数之间的随机整数,可以取到两端
      print(random.randint(1, 6))
      
    1. random.sample
    • 随机抽样,自定义抽样个数
      print(random.sample(['唐可可', '平安名堇', '穗乃果', '矢泽妮可', '星空凛'], 2))
      
  • 4.random.shuffle
    • 随机打乱顺序
      l1 = ['东','西','南','北','中','白板','发财']
      random.shuffle(l1)
      print(l1)
      

搜狗笔试题

  • 编写python代码产生随机五位数的验证码
# 定义一个函数,将参数n传入
def getcode(n):
    # 定义一个全局的code变量用于存储验证码
    code =''        
    for i in range(n):
        random_int = str(random.randint(0, 9))        # 随机产生一个0-9的数字
        random_lower = chr(random.randint(97, 122))   # 随机产生一个a-z的小写字母   assic码
        random_upper = chr(random.randint(65, 90))    # 随机产生一个A-Z的大写字母
        # 将上面三个数据值随机挑选一个作为验证码的一位数据
        temp = random.choice([random_int, random_lower,random_upper])
        code += temp           # 拼接字符串
    return code                # 返回拼接的code
# 我们需要几位的验证码,就直接调用时直接指定一下就好
res = getcode(4)
print(res)

hashlib加密模块

  • 什么是加密?
    • 将明文数据处理为密文数据的过程
  • 为啥要加密?
    • 为了不让数据轻易泄露
  • 判断当前数据值是否加密?
    • 加密后的结果一般是一串没有规律数字字母符号
  • 常见的算法
md5
sha系列
hmac
base64
  • 加密算法
    • 加密算法就是对明文数据采用的加密策略
      • 不同加密算法对相同数据加密所得长度,复杂程度也不尽相同。
      • 加密后的结果越长,一般说明加密算法越复杂
  • 代码模拟
import hashlib              # 导入hashlib加密模块
md5 = hashlib.md5()         # 选择md5作为加密方式
md5.update(b'666')          # 添加明文数据666
res =md5.hexdigest()        # 获取加密后的结果
print(res)                  # 结果: fae0b27c451c728867a567e8c1bb4e53
  • 加密模块补充
    • 1.加密模块一般不能进行反解密
    • 2.只要明文数据相同采用相同加密算法得出的密文也相同
      • md5加密往里面添加明文数据必须为bytes类型
    • 3.加盐处理
      • 加盐就是往密文内添加干扰数据,让数据更难被反解
      import hashlib
      md5 = hashlib.md5()
      password = input('password>>>:').strip()
      md5.update('设置的盐(干扰项)'.encode('utf8'))
      md5.update(password.encode('utf8'))
      res = md5.hexdigest()
      print(res)
      
    • 4.动态加盐
      • 动态加盐可以让每一次干扰项都不一样,再一次提高了数据的安全性
            加盐可以每次获取当前时间,每个用户用户名截取一段,然后生成变化的干扰项    
      
    • 5.加密的实际应用
      • 1.用户密码加密
        注册存储密文,登录也是比对密文 
        
      • 2.文件的安全性校验
        	正规的软件程序写完之后做一个内容的加密
             网址提供软件文件记忆该文件内容对应的密文
                 用户下载完成后不直接运行 而是对下载的内容做加密
         	    然后比对两次密文是否一致 如果一致表示文件没有被改
                         不一致则表示改程序有可能被植入病毒
        
      • 3.大文件加密
          针对大文件的加密一般是将大文件中的内容分段,截取小部分内容进行加密
               * 例如:对一个1TB的文件每隔2GB读取1bytes
        

subprocess远程命令模块

  • 模拟计算机的cmd命令窗口
# 调取模块
import subprocess

cmd = input('请输入您的指令>>>:').strip()
sub = subprocess.Popen(cmd,
                       shell=True,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE
)

# stdout执行命令之后正确的返回结果
print(sub.stdout.read().decode('gbk'))
# stderr执行命令报错之后的返回结果
print(sub.stderr.read().decode('gbk'))

loggin日志模块

日志的简介

  • 什么是日志?
    • 记录发生事件的时间,状态之类的
  • 为什么要使用日志?
    • 为了记录事件发生的事实
  • 日志的分级?
    • 使用日志前先要导入日志模块logging
          logging.debug('debug等级')  # 10
          logging.info('info等级')  # 20
          logging.warning('warning等级')  # 默认从warning级别开始记录日志  30
          logging.error('error等级')  # 40
          logging.critical('critical等级')  # 50
    
  • 基本使用
import logging

file_handler = logging.FileHandler(filename='l1.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('我不好!!!')
  • 输出结果: image.png

日志模块的组成

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.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.debug('日志模块')

实战应用

  • 按照软件开发目录规范编写使用
  • 日志字典数据应该放在那个py文件里?
    • log目录下的.log文件
  • 字典数据是日志模块固定的配置文件,写完一次之后几乎都不需要动。
    • 配置文件中变量名推荐全大写
import logging.config

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