今日内容回顾

openpyxl模块读取数据

其实openpyxl并不擅长读取数据。

还有一些模块在它原有的基础上优化了读取方式。

代码示例:

from openpyxl import load_workbook  # 导入模块
wb = load_workbook(r'111.xlsx',data_only=True)
print(wb.sheetnames)  # 查看excel文件中所有的工作簿名称  ['信息表']
wb1 = wb['信息表']
print(wb1.max_row)  # 查看工作簿中共有多少行
print(wb1.max_column)  # 查看工作簿中共有多少列
print(wb1['A1'].value)  # 根据表格中的A1对应的位置取值 取出工作簿中位置所对应的数据
print(wb1.cell(row=2,column=2).value)  # 第二种取值方式 根据具体位置数据所在的多少行多少列取值

# 循环取值1 循环取出表格中所有数据
for i in wb1.rows:  # 循环取出每行
    print([j.value for j in i]) # 循环将每行中的数据打印出来结果是列表形式
"""
[0, '姓名', '年龄', '性别']
[1, 'jason', 27, '男']
[2, 'mmm', 25, '男']
[3, 'lili', 24, '女']
[4, 'kkk', 48, '男']
[5, 'lll', 58, '男']
"""

# 循环取值2 循环取出表格中所有数据
for j in wb1.columns:  # 循环取出每列
    print([i.value for i in j])  
"""
['姓名', 'jason', 'mmm', 'lili', 'kkk', 'lll']
['年龄', 27, 25, 24, 48, 58]
['性别', '男', '男', '女', '男', '男']
"""

爬取数据实战之链家

import requests
import re

for numb in range(101):
    lj_website = 'https://sh.lianjia.com/ershoufang/pg%s/' % numb
    lj_data = requests.get(lj_website)
    with open(r'lj_secondhand.html', 'ab') as f:
        f.write(lj_data.content)
res1 = time.time()
print(res1-res)
with open(r'lj_secondhand.html', 'r', encoding='utf8') as f:
    lj_data = f.read()

list1 = re.findall(
    '<a class="" href=".*?" target="_blank" data-log_index=".*?"  data-el="ershoufang" data-housecode=".*?" data-is_focus="" data-sl="">(.*?)</a>',
    lj_data
)
list2 = re.findall('href=".*?" target="_blank" data-log_index=".*?" data-el="region">(.*?) </a>', lj_data)
list3 = re.findall('   -  <a href=".*?" target="_blank">(.*?)</a>', lj_data)
list4 = re.findall('<span class="houseIcon"></span>(.*?)</div>', lj_data)
list41 = []
list42 = []
list43 = []
for i in list4:  # # 2室2厅 | 96.46平米 | 南 北 | 精装 | 中楼层(共6层) | 2007年建 | 板楼
    i = i.strip()
    i = i.split(' | ')
    list41.append(i[0]+','+i[1]+','+i[2],)
    list42.append(i[3]+','+i[4])
    if 7 == len(i):
        list43.append(i[5]+','+i[6])
    else:
        list43.append(i[5])
print(list43)
print(len(list43))
list5 = re.findall(
    '<div class="followInfo"><span class="starIcon"></span>(.*?)</div>',
    lj_data
)

list6 = re.findall(
    '<div class="totalPrice totalPrice2"><i> </i><span class="">(.*?)</span><i>万</i></div>',
    lj_data
)  # 共计数据3030 爬取3029条少了一条...
list7 = re.findall(
    '<div class="unitPrice" data-hid=".*?" data-rid=".*?" data-price=".*?"><span>(.*?)</span></div>',
    lj_data
)
import pandas

d = {
    '房屋标题': list1,
    '小区名称': list2,
    '所在街道': list3,
    '户型,面积,朝向': list41,
    '状况,楼层': list42,
    '建造年份,楼栋状况': list43,
    '其他信息': list5,
    '房屋总价': list6,
    '房屋单价': list7,
}
df = pandas.DataFrame(d)
df.to_excel(r'333.xlsx')

random随机数模块

  • random.random

    返回0到1之间随机的小数,

    import random
    print(random.random())  # 0.06719751436154253
    
  • random.randint

    返回1到6之间的随机整数。其中包括1和6

    import random
    print(random.randint(1,6))
    
  • random.choice

    随机抽取其数据集内的其中一个数据值。

    import random
    print(random.choice(['特等奖','一等奖''二等奖''三等奖' '谢谢惠顾',]))  # 随机抽取一个
    
  • random.sample

    随机抽取数据值,可以自定义抽取数量

    import random
    print(random.sample(['特等奖','一等奖''二等奖''三等奖' '谢谢惠顾',],3))  # 随机抽取三个
    
  • random.shuffle

    随机打乱列表中的位置

    import random
    l1=['特等奖','一等奖','二等奖','三等奖', '谢谢惠顾',]
    random.shuffle(l1)
    print(l1)  # ['特等奖', '一等奖', '谢谢惠顾', '二等奖', '三等奖']
    
  • 笔试题

    编写python代码 产生五位随机验证码(数字、小写字母、大写字母)

    code = ''  # 定义全局变量用于存储所有的验证码
    import random
    for i in range(5):
     # 每次循环都应该产生 数字 小写字母 大写字母
        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  # 拼接字符串
     print(code)  # BxhHu
    
    
    # 也可以封装成函数形式
    def get_code(n):
        code = ''  # 定义全局变量用于存储所有的验证码
        # 编写python代码 产生五位随机验证码(数字、小写字母、大写字母)
        for i in range(n):
            # 每次循环都应该产生 数字 小写字母 大写字母
            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)
    print(res)
    res1 = get_code(10)
    print(res1
    

hashlin加密模块

  • 加密

    加密就是将明文数据(看的懂的数据)经过处理后变成密文数据(看不懂的数据)的过程

    加密可以让敏感的数据步轻易的泄露

    一般情况下如果是一串没有规则的数字、符号、字母的组合一般都是加密之后的结果

  • 加密算法

    就是对明文数据采用的加密策略

    不同的加密算法复杂度不一样,得出的结果长短也不一样

    通常情况下加密之后的结果越长,说明采用的加密算法越复杂

  • 常见的加密算法

    md5 、 sha系列、hmac、base64

  • 代码实战

    import hashlib
    
    md5 = hashlib.md5() # 选择md5加密算法作为数据的加密策略
    md5.update(b'aaa') # 往里面添加明文数据 数据必须是bytes类型
    print(md5.hexdigest())  # 打印加密之后的结果 47bce5c74f589f4867dbd57e9ca9f808
    
加密模块之补充
  1. 加密之后的结果一般情况下不能反解密

    所谓的反解密很多时候其实是偷换概念

    提前假设别人的密码是什么,然后用各种算法算出对应的密文

    之后构造对应关系然后比对密文最终映射明文

  2. 只要明文数据是一样的那么采用相同的算法得出的密文肯定一样

    import hashlib
    md5 = hashlib.md5()  # 选择md5加密算法作为数据的加密策略
    md5.update(b'aaa')   # 往里面添加明文数据 数据必须是bytes类
    md5.update(b'bbb')
    md5.update(b'ccc')
    print(md5.hexdigest())  # d1aaf4767a3c10a473407a4e47b02da6
    
    md5.update(b'aaabbbccc') 
    print(md5.hexdigest())  # d7f2f48c64921d5563d800529c7835c9
    
  3. 加盐处理

    加盐处理指的是在加密的过程中在添加一些干扰项,增加密文的复杂度。

    import hashlib
    md5 = hashlib.md5()
    # 示例1 加盐处理之前
    md5.update(b'aaa')  # 47bce5c74f589f4867dbd57e9ca9f808
    print(md5.hexdigest())
    # 示例2 加盐处理之后
    md5.update('干扰项'.encode('utf8'))
    # 在加密真正的明文之前先加入一个干扰项
    md5.update(b'aaa')
    print(md5.hexdigest())  # 93c9fb7d2e93ec6b7eff252194b678e9
    
  4. 动态加盐

    动态加盐指的是每次在加密之前设置的干扰项每次都不同,

    可能是每次获取当前时间,可能是截取用户名的一段

    这个相比固定加盐处理更加复杂些。

  5. 加密实际应用场景

    5.1 用户密码注册加密

    用户注册密码后将其密码加密后存入数据库。

    用户登录时将其密码加密后用来比对数据库的密码密文,一致后可登录。

    5.2 文件安全校验

    正规的软件程序写完之后做一个加密处理,写入文件中。

    网址提供软件,文件记忆该软件对应的密文

    用户下载完成后步直接运行,而是对下载的内容做加密

    然后比对跟文件中的密文做比对是否一致,如果一致表示改软件没有被修改过

    不一致可能在基于网络传输的时候被不法分子截取,植入过病毒,

    5.3 大文件加密

    当一个程序文件过大比如次文件有100G

    一般情况下读取100G内容然后全部加密,速度太慢

    我们可以换个方式 不对100G中全部内容加密,采用截取的方式

    一部分,一部分的加密比如每隔500M读取30bytes用于加密。

subprocess远程命令模块

subprocess模块时用于模拟计算机cmd命令窗口

代码操作:

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'))

logging日志模块

日志就是类似于历史记录,也就是为了记录事物发生的事实。

  • 日志的使用

    1. 日志的等级

      首先使用日志要先了解它,其中日志可以简单的分为五个级别

      import logging
      logging.debug('debug等级')  # 10
      logging.info('info等级')  # 20
      logging.warning('warning等级')  # 默认从warning级别开始记录日志  30
      logging.error('error等级')  # 40
      logging.critical('critical等级')  # 50
      
    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('记录日志')
      
日志模块的组成部分
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('CV真的好开心')


"""
我们在记录日志的时候 不需要向上述一样全部自己写 过于繁琐
所以该模块提供了固定的配置字典直接调用即可
"""
日志配置字典

配套齐全需要用到日志的时候来这里CV

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
posted @   瓮小辉  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示