openpyxl知识点补充,pandas模块基础、random模块、subprocess模块、logging模块、练习

openpyxl模块知识补充——读取数据

openpyxl对读取excel文件不是很方便,pandas模块优化了读取的方式

1.查看excel文件中所有工作簿名称

load_workbook.sheetnames

from openpyxl import Workbook,load_workbook
wb = Workbook()
ws1 = wb.create_sheet("学生信息表")
ws2 = wb.create_sheet("学生成绩表")
ws1.append(["姓名","年龄","性别"])
ws1.append(["张三",18,"男"])
ws1.append(["李四",19,"女"])
ws1.append(["老王",20,"男"])
ws1.append(["小黑",23,"男"])
wb.save("学生信息表.xlsx")

wd = load_workbook(r'学生信息表.xlsx')
print(wd.sheetnames)  # ['Sheet', '学生信息表', '学生成绩表']

2.查看指定excel文件工作簿的最大行、最大列

worksheet.max_row 、 worksheet.max_column

wd = load_workbook(r'学生信息表.xlsx')
wd1 = wd['学生信息表']
print(wd1)  # <Worksheet "学生信息表">
print(wd1.max_row)  # 5
print(wd1.max_column)  # 3

3.读取特定的值——两种方式

第一种方式:指定位置信息.value 第二种方式:worksheet.cell(行,列).value

wd = load_workbook(r'学生信息表.xlsx')
wd1 = wd['学生信息表']
print(wd1['A1'].value)  # 姓名
print(wd1.cell(row = 3,column = 2).value)  # 19

4.查看excel文件指定工作簿的所有行、列

worksheet.rows(columns) 用for循环嵌套,用.value读取出来

wd = load_workbook(r'学生信息表.xlsx')
wd1 = wd['学生信息表']
print(wd1.rows)  # <generator object Worksheet._cells_by_row at 0x00000255FB87B4C0>
for i in wd1.rows:
    # print(i)  # (<Cell '学生信息表'.A1>, <Cell '学生信息表'.B1>, <Cell '学生信息表'.C1>)....
    print([j.value for j in i ]) # ['姓名', '年龄', '性别']   ['张三', 18, '男']....
for j in wd1.columns:
    print(j)  # (<Cell '学生信息表'.A1>, <Cell '学生信息表'.A2>, <Cell '学生信息表'.A3>, <Cell '学生信息表'.A4>, <Cell '学生信息表'.A5>)...
    print([i.value for i in j])  # ['姓名', '张三', '李四', '老王', '小黑']  # ['年龄', 18, 19, 20, 23]...

pandas模块

pandas模块功能强大,创建excel文件更加简洁方便

import pandas
d = {
    '姓名':['张三','李四','老王','小黑'],
    "年龄":[18,19,20,23],
    "性别":['男','女','男','男']
}
df = pandas.DataFrame(d)
df.to_excel(r"学生信息.xlsx")

网络爬虫实战--爬取链家二手房数据

https://sh.lianjia.com/ershoufang/

import requests
import re
import pandas
res1 = requests.get("https://sh.lianjia.com/ershoufang/")
with open(r'lianjia.html','wb')as f:
    f.write(res1.content)
with open(r'lianjia.html','r',encoding='utf8') as f:
    data = f.read()
home_title = re.findall('<a class="" href=".*?" target="_blank" data-log_index=".*?"  data-el=".*?" data-housecode=".*?" data-is_focus="" data-sl="">(.*?)</a>',data)
home_name = re.findall('<a href=".*?" target="_blank" data-log_index=".*?" data-el=".*?">(.*?) </a>',data)
home_address = re.findall('   -  <a href=".*?" target="_blank">(.*?)</a>',data)
home_detail_info = re.findall('<span class="houseIcon"></span>(.*?)</div>',data)
home_follow_info =re.findall('<div class="followInfo"><span class="starIcon"></span>(.*?)</div>',data)
home_all_price =re.findall('<div class=".*?"><i> </i><span class="">(.*?)</span>',data)
home_unit_price = re.findall('<div class=".*?" data-hid=".*?" data-rid=".*?" data-price=".*?"><span>(.*?)</span>',data)

d = {
    '标题':home_title,
    '小区名称':home_name,
    '小区地址':home_address,
    '房屋详细信息':home_detail_info,
    '房屋收藏信息':home_follow_info,
    '房屋单价':home_unit_price,
    '房屋总价(万)':home_all_price
}
res = pandas.DataFrame(d)
res.to_excel(r'链家房屋信息.xlsx')

random随机数模块

1.random()

返回0-1之间的随机数

import random
print(random.random())  # 0.49781208840423374
print(random.random())   # 0.2810934030122708

2.randint(a,b)

返回a-b之间的随机整数

import random
print(random.randint(2, 7)) # 5
print(random.randint(2, 7))  # 6

3.choice()

随机抽取容器类型里面的数据值

import random
print(random.choice(['一等奖','二等奖','三等奖']))  # 三等奖
print(random.choice(['一等奖','二等奖','三等奖']))  # 二等奖

4.sample()

随机抽样,自定义抽样的个数

import random
print(random.sample(['A', 'B', 'C', 'D', 'E', 'F', 'G'], 3))  # ['C', 'G', 'B']
print(random.sample(['A', 'B', 'C', 'D', 'E', 'F', 'G'], 3))  # ['B', 'G', 'F']

5.shuffle()

可以将容器类型的数据排列打乱

import random
l1 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A', '大王', '小王']
random.shuffle(l1)
print(l1)  # [3, 4, 'Q', 10, 5, 'A', 8, 2, '大王', 6, '小王', 9, 'K', 7, 'J']

random模块实战

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

import random
code = ''
for i in range(5):
    res1 = str(random.randint(0,9))
    res2 = chr(random.randint(65,90))
    res3 = chr(random.randint(97,122))
    num = random.choice([res1,res2,res3])
    code += num
print(code)  # BY84f

print(code)  # bea9P

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

import random
def num_code(n):
    code = ''
    for i in range(n):
        res1 = str(random.randint(0,9))
        res2 = chr(random.randint(65,90))
        res3 = chr(random.randint(97,122))
        num = random.choice([res1,res2,res3])
        code += num
    return code

print(num_code(4))  # fi8a
print(num_code(5))  # jIw2I
print(num_code(6))  # 4X1LX0

hashlib加密模块

1.什么是加密
	将明文数据经过处理之后变成密文数据的过程
2.为什么加密
	防止隐私泄露
3.如何判断当前数据值是否已经加密
	一般情况下,如果是一串没有规则的数字字母符号的组合,一般都是加密之后的结果
4.加密算法:对明文数据采用的加密策略
   ps:不同的加密算法复杂程度不一样,得出的结果舱段也不一样
       一般加密之后的结果越长,说明采用加密的算法越复杂
5.常见的加密算法:md5、sha系列、hmac、base64
6.加密之后的结果一般情况下不能反解密
	ps:所谓的反解密很多时候其实时偷换概念:提前假设别人的密码是什么,然后用过各种算法算出对应的密文,之后构造出对应的关系,然后比对密文,最后映射密文{'密文1':123,'密文2':321,...}

hashlib代码实战

基础练习

import hashlib
m1 = hashlib.md5() # 选择md5加密算法作为数据的加密策略
m1.update(b'123')  # 往里面添加明文数据,数据必须是Bytes类型
res = m1.hexdigest()  # 获取加密之后的结果
print(res)  # 202cb962ac59075b964b07152d234b70

加盐处理

对待加密的明文在加密之前,添加一些干扰的字符串;同时也有动态加盐,即干扰项每一次都不一样,例如每次获取当前的时间、每个用户用户名截取一段

import hashlib
pwd = input("请输入你的银行卡密码>>>:").strip()
m1 = hashlib.md5()
m1.update('中国银行(干扰项)'.encode('utf8'))
m1.update(pwd.encode('utf8'))
res = m1.hexdigest()
print(res)  # 21c0b48cc5b84847e4bcdb542d34cceb

补充

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

import hashlib
m1 = hashlib.md5()
m1.update(b'123')
m1.update(b'ABC')
m1.update(b'dfg')
res = m1.hexdigest()
print(res)  # 42cef12be984c329ff47e5a887d17c4c

import hashlib
m1 = hashlib.md5()
m1.update(b'123ABCdfg')
res = m1.hexdigest()
print(res)  # 42cef12be984c329ff47e5a887d17c4c

加密实际应用场景

1.用户密码加密:注册存储加密、登陆比对密文
2.文件安全性校验
	正规的软件程序写完之后会做一个内容加密;网址提供软件文件记录该文件内容对应的密文;用户下载完毕后不直接运行,而是对下载的内容做加密,然后比对两次密文是否一致。如果一致表示文件没有被改动,可运行;如果不一致,则表示改程序有可能被植入病毒
3.大文件加密优化
	例如:程序文件100G,需要加密处理,怎样加密
    一般情况,读取100G内容然后全部加密,会运行很慢,所以不对100G所有内容加密,而是截取一部分加密,例如:每隔500M读取30bytes

subprocess模块

subprocess是模拟cmd命令窗口

import subprocess
cmd = input("输入您的指令:>>>").strip()
sub = subprocess.Popen(
    cmd,
    shell=True,
    stdout = subprocess.PIPE,
    stderr= subprocess.PIPE
)
# print(sub.stdout.read())  # 二进制的数据
# stdout执行命令之后正确的返回结果
print(sub.stdout.read().decode('gbk'))   
# stderr执行命令报错之后返回的结果
print(sub.stderr.read().decode('gbk'))

logging日志模块

简介

1.什么是日志
	日志就类似于历史记录
2.为什么要使用日志
	为了记录事物发生的事实
3.如何使用日志
	3.1 日志等级(5个)
    import logging
    logging.debug('debug等级')  # 10
    logging.info('info等级')  # 20
    logging.warning('warning等级')  # 30 默认从warning级别开始记录日志
    logging.error('error等级')  # 40
    logging.critical('critical等级')  # 50
    >>> WARNING:root:warning等级
    >>> ERROR:root:error等级
    >>> CRITICAL:root: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('你好') 
    >>> 2022-07-21 18:04:55 PM - root - ERROR -logging模块:  你好
    

日志模块的组成部分

有logger对象(日志的产生)、filter对象(日志的过滤,可以忽略)、handler对象(日志的产出)、format对象(日志的格式)

import logging

# 1.日志的产生(相当于准备原材料)>>>logger对象
logger = logging.getLogger('购物车记录')
# 2.日志的过滤(剔除不良品)>>>filter对象(可以忽略)
# 3.日志的产出(成品)>>>handler对象
hd1 = logging.FileHandler('a1.log', encoding='utf-8')  # 输出a1.log文件中
hd2 = logging.FileHandler('a2.log', encoding='utf-8')  # 输出到a2.log文件中
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绑定format对象
hd1.setFormatter(fm1)
hd2.setFormatter(fm2)
hd3.setFormatter(fm1)
# 7.设置日志等级
logger.setLevel(10)  
# 8.记录日志
logger.debug('写了半天 好累啊 好热啊')

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

日志配置字典

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注册成功')

实战应用

1.将日志字典放在配置文件内(conf文件夹中的setings.py),因为字典数据时日志模块固定的配置,写完一次之后几乎都不需要动
	ps:配置文件中变量名推荐大写
2.将最后记录产生日志的步骤中,封装成函数,放在公共的lib文件夹中的common.py文件中
def get_logger(msg):
    # 记录日志
    logging.config.dictConfig(settings.LOGGING_DIC)  # 自动加载字典中的配置
    logger1 = logging.getLogger(msg)
    # logger1.debug(f'{username}注册成功')  # 这里让用户自己写更好
    return logger1
ps: 有返回值是因为,可以之后更加灵活的添加日志等级

作业

思考链家二手房多页数据如何爬取

# 第一页:https://sh.lianjia.com/ershoufang/pg1/
# 第二页:https://sh.lianjia.com/ershoufang/pg2/
# 第三页:https://sh.lianjia.com/ershoufang/pg3/
# 第一百页:https://sh.lianjia.com/ershoufang/pg100/
import requests
import re
import pandas
base_path = "https://sh.lianjia.com/ershoufang/pg%s/"
for i in range(1,101):
    data = requests.get(base_path%i)
    res1 = requests.get("https://sh.lianjia.com/ershoufang/")
    with open(r'lianjias.html', 'ab')as f:
        f.write(res1.content)
with open(r'lianjias.html', 'r', encoding='utf8') as f:
    data = f.read()
home_title = re.findall(
    '<a class="" href=".*?" target="_blank" data-log_index=".*?"  data-el=".*?" data-housecode=".*?" data-is_focus="" data-sl="">(.*?)</a>',
    data)
# print(home_title)
home_name = re.findall('<a href=".*?" target="_blank" data-log_index=".*?" data-el=".*?">(.*?) </a>', data)
# print(home_name)
home_address = re.findall('   -  <a href=".*?" target="_blank">(.*?)</a>', data)
# print(home_address)
home_detail_info = re.findall('<span class="houseIcon"></span>(.*?)</div>', data)
# print(home_detail_info) # ['2室2厅 | 96.46平米 | 南 北 | 精装 | 中楼层(共6层) | 2007年建 | 板楼']
home_follow_info = re.findall('<div class="followInfo"><span class="starIcon"></span>(.*?)</div>', data)
# print(home_follow_info)
home_all_price = re.findall('<div class=".*?"><i> </i><span class="">(.*?)</span>', data)
# print(home_all_price)
home_unit_price = re.findall('<div class=".*?" data-hid=".*?" data-rid=".*?" data-price=".*?"><span>(.*?)</span>',
                             data)
# print(home_unit_price)

d = {
    '标题': home_title,
    '小区名称': home_name,
    '小区地址': home_address,
    '房屋详细信息': home_detail_info,
    '房屋收藏信息': home_follow_info,
    '房屋单价': home_unit_price,
    '房屋总价(万)': home_all_price
}
res = pandas.DataFrame(d)
res.to_excel(r'链家房屋信息(s).xlsx')
posted @   DRAMA-娜娜  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示