正则表达式与机数模块、加密模块、日志模块
正则表达式
什么是正则表达式
正则表达式就是根据字符组合产生的规则,从字符串中筛选想要的数据
正则表达式特殊符号
. 除了换行符以外的所有字符
\w 只匹配数字、字母、下划线
\s 只匹配空白字符
\d 只匹配数字
\b 只匹配单词的开头或结尾
^ 只匹配字符串的开始
$ 只匹配字符串的结尾
| 匹配管道符左边或右边的字符
() 给表达式分组
[] 匹配符合字符组中的东西
[^] 匹配除了字符组中的东西
正则表达式量词
* 重复零次或更多次,尽可能多的取
+ 重复一次或更多次,尽可能多的取
? 重复零次或一次,只取一次
{n} 重复n次
{n, } 重复n次到更多次
{n, m} 重复、n次到m次
正则表达式贪婪与非贪婪
1.所有正则表达式量词都默认贪婪匹配,只有在量词后面加问号?才是非贪婪匹配
2.在使用贪婪或非贪婪匹配时,如.*和.?,结束位置由这俩个符号左右的表达式决定
匹配文本:<akjshdja>askjd<ajlofd>akjswdh
正则表达式:<.*> #贪婪匹配
匹配结果:<akjshdja>askjd<ajlofd>
正则表达式:<.*?> #非贪婪匹配
匹配结果:
<akjshdja>
<ajlofd>
正则表达式取消转义
"正则表达式取消斜杠与字母的特殊含义,就在前面加斜杠"
匹配文本 表达式 匹配结果
\n \\n \n
\\n \\\\n \\n
re模块
re模块基础使用
-
re模块是python使用的正则表达式的方法之一
-
findall
findall括号第一个是正则表达式,第二个是被筛选字符串,将筛选结果组成列表
import re
res = re.findall('r', 'barry run rr') # 筛选符合正则表达式的数据
print(res)
# run:['r', 'r', 'r', 'r', 'r']
-
finditer
finditer和findall作用一致,不过筛选出来的结果处理成迭代器对象,用于节省内存
import re
res = re.finditer('r', 'barry run rr') # 筛选符合正则表达式的数据处理成迭代器对象
print(res)
# run:<callable_iterator object at 0x000001AC9DED8430>
print(res.__next__())
# run:<re.Match object; span=(2, 3), match='r'>
-
search
search只有筛选到一个结果就会结束,输出以匹配到对象和所在位置,通过group就可以变回以匹配对象
import re
res = re.search('r', 'barry run rr') # 筛选一个符合正则表达式的数据就结束
print(res)
# run:<re.Match object; span=(2, 3), match='r'>
print(res.group())
# run:r
- match只筛选开始的第一个数据,若是匹配成功则结束,若是匹配不成功则结束并返回None
import re
res = re.match('r', 'barry run rr') # 只筛选开始的一个数据是否符合正则表达式
print(res)
# run:None
res = re.match('r', 'rry run rr') # 只筛选开始的一个数据是否符合正则表达式
print(res)
# run:<re.Match object; span=(0, 1), match='r'>
print(res.group())
# run:r
-
compile
compile括号内部是准备好的正则表达式,在需要使用时直接使用正则绑定的变量名即可
import re
res = re.compile('r') # 提前准备好正则表达式
print(re.findall(res, 'rry run rr'))
# run:['r', 'r', 'r', 'r', 'r']
print(re.findall(res, 'ekwererkrk23'))
# run:['r', 'r', 'r']
re模块补充
- 在findall括号内用()将正则表达式括起来,是优先展示括号内匹配的结果的意思
res = re.findall('a(b)cd', 'abcdabcdabcd') # findall优先展示括号内匹配的结果
print(res)
# run:['b', 'b', 'b']
res = re.findall('a(b)(c)d', 'abcdabcdabcd') # 若有两个括号,则优先展示括号内匹配的结果,在将结果组成元组组成列表
print(res)
# run:[('b', 'c'), ('b', 'c'), ('b', 'c')]
res = re.findall('a(?:b)cd', 'abcdabcdabcd') # findall在括号内加?:可以取消优先展示
print(res)
# run:['abcd', 'abcd', 'abcd']
- 在search括号内用()将正则表达式括起来,可以用group选择优先展示那个括号的匹配结果
res = re.search('a(b)(c)d', 'abcdabcdabcd') # 优先展示括号内匹配的结果
print(res.group()) # 加group取消优先展示
# run:abcd
print(res.group(0)) # group括号内是0和没有一样是取消优先展示
# run:abcd
print(res.group(1)) # group括号内是1优先展示第1个括号的匹配结果
# run:b
print(res.group(2)) # group括号内是2优先展示第2个括号的匹配结果
# run:c
- 在search括号内用?P<>可以将优先展示的匹配结果加个对应的名字,这样就可以用group括号里加名字,选择优先展示名字的匹配结果
res = re.search('a(?P<id>b)(?P<name>c)','abcdabcdabcd') # 在()内?P<后写名字>后写名字对应的筛选条件
print(res.group()) # 加group取消优先展示
# run:abc
print(res.group(1)) # group括号内是1优先展示第1个括号的匹配结果
# run:b
print(res.group('id')) # group括号内可以根据名字获取名字对应的匹配结果
# run:b
print(res.group('name')) # group括号内可以根据名字获取名字对应的匹配结果
# run:c
网络爬虫
网络爬虫简介
1.互联网
互联网可以将计算机连接到一起,让接入互联网的计算机可以共享数据,有些计算机是专门让别人访问的,被称为服务器,让我们可以通过互联网使用别人的资源
2.网络爬虫的本质
网络爬虫本质上是通过一些规则,自动获取信息的程序
网络爬虫本质上是模拟计算机浏览器朝目标发送请求返回数据并筛选,只要浏览器可以访问的数据网络爬虫理论上都可以
3.网络爬虫虽然好用,但要合法使用,不然一不小心就会获得银手镯
第三方模块下载
- cmd
1.第三方模块需要下载才可以导入使用,python下载第三方模块需要pip工具
2.下载命令
pip3.8 install 模块名
3.下载的问题
3.1下载速度很慢
pip工具默认从国外下载模块,可以更换下载地址源
pip3.8 install 模块名 -i 源地址
"""
下载源地址
中科院:https://pypi.mirrors.ustc.edu.cn/simple/
清华大学 :https://pypi.tuna.tsinghua.edu.cn/simple/
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科学技术大学 :http://pypi.mirrors.ustc.edu.cn/simple/
华中科技大学:http://pypi.hustunique.com/
豆瓣源:http://pypi.douban.com/simple/
腾讯源:http://mirrors.cloud.tencent.com/pypi/simple
华为镜像源:https://repo.huaweicloud.com/repository/pypi/simple/
"""
3.2下载报错
"""
1.pip工具版本过低,拷贝信息提示里的共享命令即可
python38 -m pip install --upgrade pip
2.网络不稳定 报错关键字Read timed out
只能重新下载,或者换一个稳定的网络
3.有些模块在下载使用之前需要提前配置指定的环境
"""
4.模块也有版本
pip3.8 install 模块名==版本号
- pycharm
pycharm也可以下载模块
File>>>settings>>>project:文件夹名>>>python lnterpreter
在右侧的界面中是现在有的模块信息,随便双击一个模块,在上方的搜索条中可以搜索需要下载的模块,点击需要下载的模块名,在点击lnstall Package下载
在lnstall Package右侧的Manage Repositories可以添加或删除下载源地址
openpyxl模块
openpyxl模块有什么用
1.我们可以通过openpyxl模块来操作Excel表格
2.在python中有很多可以操作Excel表格的模块,openpyxl模块是近年比较热门的模块,但openpyxl模块对03之前的Excel版本兼容性不好
3.xlwt、xlrd也可以操作Excell表格,可以兼容所有版本的Excel表格,但没有openpyxl简单
4.分辨Excel版本
03年之前的excel文件的后缀名 .xls
03年之后的excel文件的后缀名 .xlsx
openpyxl模块的使用
from openpyxl import Workbook # 导入模块
wb = Workbook() # 创建Excel文件
wb1 = wb.create_sheet('魏国') # 创建表格名字
wb2 = wb.create_sheet('蜀国', 0) # 可选择表格位置
wb1.title = '曹操' # 可以修改表格的名字
wb1.sheet_properties.tabColor = '1072BA' # 修改表格的颜色
wb2['B2'] = '赵云' # 将赵云写入表格的B行2列
wb2.cell(row=3, column=1, value='关羽') # 将关羽写入表格的3行1列
# 批量写入
wb2.append(['name', 'pwd', 'age', 'hobby'])
wb2.append(['jay', '123', '20', 'run'])
wb2.append(['barry', '123', '20', 'run'])
wb2.append(['wally', '123', '20', 'run'])
wb2.append(['bart', '123', '20', 'run'])
wb.save(r'110.xlsx') # 保存文件
openpyxl模块读取数据
from openpyxl import load_workbook
wb = load_workbook(r'110.xlsx', data_only=True) #
print(wb.sheetnames) # 将文件的工作簿组成列表输出
# ['Sheet', '闪电家族']
wb1 = wb['闪电家族'] # 选择工作牌的名字或索引取值
print(wb1.max_row) # 工作簿有多少行
# 5
print(wb1.max_column) # 工作簿有多少列
# 4
print(wb1['A3'].value) # 将工作簿第2行3列输出
# barry
print(wb1.cell(row=2, column=3).value) # 将工作簿第2行3列输出
# 20
for i in wb1.columns:
print([j.value for j in i]) # 将工作簿按列组成列表输出
# ['name', 'jay', 'barry', 'wally', 'bart']
# ['pwd', '123', '123', '123', '123']
# ['age', '20', '20', '20', '20']
# ['hobby', 'run', 'run', 'run', 'run']
"""
openpyxl读取数据比较麻烦,有一些模块优化了读取方法
如:pandas模块
"""
random随机数模块
import random
print(random.random()) # 随机返回0到1之间的任意小数
# 0.006087422886232985
print(random.randint(1, 6)) # 随机返回1到6之间的任意整数
# 6
print(random.choice(['老魔杖', '无限宝石', '贤者之石', '神速力', '万花筒写轮眼'])) # 随机返回括号内的任意数据
# 神速力
print(random.sample(['老魔杖', '无限宝石', '贤者之石', '神速力', '万花筒写轮眼'], 2)) # 自定义随机返回括号内的任意数据的个数
# ['贤者之石', '老魔杖']
pk = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A', '小王', '大王']
random.shuffle(pk) # 随机返回1到6之间的任意整数
print(pk)
# [4, 9, '大王', 10, 'K', 6, 3, 'A', 2, 8, 5, 7, 'Q', '小王', 'J']
hashlib加密模块
加密
1.什么是加密
加密就是把能看懂的明文数据处理成看不懂的密文数据
2.为什么要加密
有些数据不能被他人获取就需要加密
3.如何判断加密
由字母和数字所组成的一串不规则数据就是加密后的密文
4.加密算法
加密算法就是对明文数据采取的加密方法
不同加密算法加密后的长短不一样,一般加密后越长,加密算法也越复杂
加密算法
1.常见的加密算法
_md5 _sha1 _sha3 hmac
2.使用方法
import hashlib
md5 = hashlib.md5() # 选择md5加密算法
md5.update(b'110') # 添加要加密的数据,数据必须是bytes类型
res = md5.hexdigest() # 获取加密结果
print(res)
# 5f93f983524def3dca464469d2cf9f3e
解密
1.加密后的结果一般是不能解密的,很多解密其实只是假设密码后,在用各种算法加密成密文,在用密文进行对比,来获取明文
2.同样的明文数据用同样的算法加密出来的密文也是一样的
import hashlib
md5 = hashlib.md5() # 选择md5加密算法
# md5.update(b'110') # 添加要加密的数据,数据必须是bytes类型
# md5.update(b'911') # 添加要加密的数据,数据必须是bytes类型
# res = md5.hexdigest() # 获取加密结果
# print(res)
# 1522c605dfa5a951ae2f552bea28e207
md5.update(b'110911')
res1 = md5.hexdigest()
print(res1)
# 1522c605dfa5a951ae2f552bea28e207
3.加盐处理(salt)
import hashlib
md5 = hashlib.md5() # 选择md5加密算法
pwd = input('pwd>>>:') # 110
md5.update('盐也就是干扰项'.encode('utf8')) # 这家干扰项
md5.update(pwd.encode('utf8')) # 将干扰项和明文一起加密
res = md5.hexdigest() # 获取加密结果
print(res)
# ebbaf98b855a5f3b387b7d5cc28394b1
4.动态加盐(salt)
干扰项每次都不一样,这样密文也每次都不一样
import hashlib, time
md5 = hashlib.md5() # 选择md5加密算法
pwd = input('pwd>>>:').strip() # 110
md5.update(f'{time.time()}'.encode('utf8')) # 这家干扰项
md5.update(pwd.encode('utf8')) # 将干扰项和明文一起加密
res = md5.hexdigest() # 获取加密结果
print(res)
# 034626de53ae1e9a5d07ccaf92fb5517
加密的实际应用
1.加密经常用在用户密码、身份信息的保护
2.文件安全性效验
正规的数据程序要对内容进行加密,下载网址提供软件文件内容对应密文,然后对比密文是否一致,若不一致则表示被更改过植入了病毒
3.大程序加密
下载文件太大时,将文件全部加密会很慢,这时候就会只加密一部分,像每隔500M加密50bytes
subprocess远程命令模块
subprocess用于模拟计算机cmd命令窗口
import subprocess
cmd = input('输入指令>>>:').strip()
sub = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(sub.stdout.read().decode('gbk'))
# stdout执行命令正确的返回结果
print(sub.stderr.read().decode('gbk'))
# stderr执行命令错误的返回结果
logging日志模块
日志模块
1.日志是用于记录事物的发生
2.日志的等级
import logging
logging.debug('debug等级') # 10
logging.info('info等级') # 20
logging.warning('warning等级') # 30
logging.error('error等级') # 40
logging.critical('critical等级') # 50
# 默认从warning等级开始记录日志
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) # 绑定hd1对象
logger.addHandler(hd2) # 绑定hd2对象
logger.addHandler(hd3) # 绑定hd3对象
# 6.给handler绑定formmate对象
hd1.setFormatter(fm1) # 使用fm1格式
hd2.setFormatter(fm2) # 使用fm2格式
hd3.setFormatter(fm1) # 使用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配置
},
}
logging.config.dictConfig(LOGGING_DIC) # 自动加载字典中的配置
logger1 = logging.getLogger('购买记录')
logger1.debug('老魔杖 贤者之石')
项目开发
项目开发流程
1.需求分析
1.1就是产品经理去问客户明确项目的主体功能要写什么东西,实现什么功能
1.2参与人员
产品经理、开发经理、架构师
1.3技术人员主要职责
引导客户提出一些比较合理、比较容易实现的需求
2.架构设计
2.1明确项目需要用到的核心技术
项目使用的编程语言、框架、数据库
2.2参与人员
架构师
3.分组开发
3.1明确每个组每个人负责的部分
3.2参与人员
架构师、开发经理、普通程序员
4.提交测试
4.1自己测试,在交由测试员测试
4.2参与人员
普通程序员、测试员
5.交付上线
5.1将完成好的项目交给客户也可以帮客户维护(定期收钱)
5.2参与人员
运维工程师
"""
大公司的开发流程比较规范,你只做你负责的那部分,但会让自己的履历很有优势,跳槽方便
小公司的开发流程没那么规范,你会负责很多事,短期内提示非常大,但是会很累
"""
项目需求分析
# 主题是带大家快速入门python直至开发一个ATM+购物车系统,ATM的实现类似于银行自助提款机核心业务,购物车的实现类似于淘宝商城购物系统。
# 该项目的核心不仅在于引领初学者快速入门python项目开发,更是站在项目架构的角度教你如何在程序开发之初合理且优雅地设计程序的架构,从而极大地提升程序的开发效率与可扩展性
"""
- 额度15000或自定义
- 支持多账户登录
- 可以查看账户余额
- 可以提现(可自定义手续费比例)
- 提供还款接口
- 支持账户间转账
- 记录每月日常消费流水
- 实现购物商城,买东西加入购物车,调用信用卡接口结账
- 提供管理接口,包括添加账户、用户额度,冻结账户等
- ATM记录操作日志
- 用户认证功能
"""
从需求中提炼出项目的核心功能
1.用户注册
2.用户登录
3.查看余额
4.账户提现
5.充值功能
6.转账功能
7.查看账单
8.购物车功能
9.管理员功能
从功能中再提炼出核心技术点
1.python核心语法
2.python诸多模块
3.装饰器
架构设计
项目架构(重要)
百度
以用户登录为例
1.浏览器页面获取用户名和密码
2.基于网络将用户名和密码发送给百度服务端
3.服务端去数据库中校验用户数据
三层架构
浏览器、服务端、数据库
淘宝
以购买商品为例
1.浏览器页面展示商品总价
2.基于网络将购买商品的操作发送给服务端做核心校验
3.之后操作相应数据库完成数据修改
三层架构
浏览器、服务端、数据库
三层架构
用户层
数据展示 数据获取
cmd窗口可以充当用户层
将来可以替换成浏览器或者app
核心逻辑层
业务逻辑
某个py文件充当逻辑层
将来可以替换成软件开发目录规范或者现成的框架
数据层
数据的增删改查
json文件充当数据库
将来可以替换成数据库程序