1 2 3 4

7 python常用模块介绍 --time datetime calendar os sys random json pickle shelve hashlib shutil logging re

1.1模块介绍

* 模块定义:一系列功能的集合体
* 模块使用: import导入模块   或者  from ... import... 导入模块
* 模块分类:内置模块    自定义模块  第三方模块
* 模块加载顺序:  内存>内置>sys.path(环境变量中的路径时逐一加载的)
* 模块起别名:  import 模块名 as 别名

  

模块两种被执行方式:

1.一个py文件作为自执行文件,__name__变量的值为 '__main__'
if __name__ == '__main__':
    # 自执行的逻辑 => 因为在文件作为模块使用时 __name__为文件名,不满足条件
    pass
2.一个py文件作为模块被导入执行,__name__变量的值为 '文件(模块)名' 
此时被其他使用

  

1.2 包的介绍

包的定义:

一系列模块的集合体,用文件件来管理一系列有联系的功能的模块,该文件夹称之为包,文件夹名就是包名

包与普通文件夹的区别:

包的文件夹中一定存在一个__init__.py文件文件

  

__init__.py文件的作用

1    产生一个全局名称空间提供给包使用 此名称空间就是包的名称空间
2  管理包		包可以直接点出来模块使用

 

导包完成的三件事

 
# 导包完成的三件事
# 1)编译形成包中__init__.py文件的pyc文件
# 2)执行__init__.py文件,形成一个全局名称空间,将__init__.py文件中所有名字存放其中,该名称空间就代表包的名称空间
# 3)在导包的文件中,产生一个与包名相同的名字,指向包的名称空间(__init__.py文件的全局名称空间)

  

包的管理

# 在包中采用相对导入管理模块或模块中的名字


# 在包的__init__.py文件或是包中任意一个模块中
# . 代表当前文件所在目录
# .. 代表当前文件所在目录的上一级目录
# 注:.语法不能出包,因为包外的文件都能自执行,但拥有.开头导入的文件不能自执行

  

1.3 项目开发周期

 
'''
1.调研
2.需求分析
3.架构师完成项目demo,完成项目架构
4.分工
5.写代码
6.白盒黑盒测试
7.项目审核发布 => 项目 -> 产品
'''

'''
bin: 可执行文件,入口,入口也可以放在项目根目录下
core: 核心代码
db:数据库相关文件
interface:接口
lib:包、模块、第三方文件夹
log:日志
setting:配置
static:静态文件
'''

  

1.4  time 模块 

"""
时间戳(timestamp):time.time()  用于数据的唯一标识  从1970年开始算的
延迟线程的运行:time.sleep()  # 几秒之后才去执行
(指定时间戳下的)当前时区时间:time.localtime()  
(指定时间戳下的)格林威治时间:time.gmtime()
(指定时间元组下的)格式化时间:time.strftime(fmt[,tupletime])
"""

  

案例

import time

# 格林威治时间
time_obj2 = time.gmtime()

print(time.time())  # 时间戳,用于数据的唯一标识


# 格式化时间 
# Y-m-d H:M:S  代表 年 月 日 时 分 秒
# (2019, 5, 6, 6, 16, 9, 0, 126, 0)
res = time.strftime("%Y-%m-%d %H:%M:%S")
print(res)
res = time.strftime("%Y-%m-%d %H:%M:%S", (2008, 8, 8, 8, 8, 8, 0, 0, 0))
print(res)


# 计算时间
starttime = time.time()

def fn():
    time.sleep(3)
    return  time.time()
res = fn() - starttime
print(res)

  

1.5 datetime模块

和time模块功能重复   掌握time模块就好

"""
当前时间:datetime.datetime.now()
昨天:datetime.datetime.now() + datetime.timedelta(days=-1)
修改时间:datetime_obj.replace([...])
格式化时间戳:datetime.date.fromtimestamp(timestamp)
"""

  

1.6 calendar模块

"""
判断闰年:calendar.isleap(year)
查看某年某月日历:calendar.month(year, mouth)
查看某年某月起始星期与当月天数:calendar.monthrange(year, mouth)
查看某年某月某日是星期几:calendar.weekday(year, month, day)
"""
import calendar
print(calendar.isleap(2200))
print(calendar.month(2019, 5))
print(calendar.monthrange(2019, 5))
print(calendar.weekday(2019, 5, 7))

  

1.7 os模块 

 
生成单级目录:os.mkdir('dirname')
生成多层目录:os.makedirs('dirname1/.../dirnamen2')
列举目录下所有资源:os.listdir('dirname')
删除文件:os.romeve('file_path')
删除单层空目录:os.rmdir('dirname')
移除多层空目录:os.removedirs('dirname1/.../dirnamen')

  

# os.mkdir('abc')  # 在当前文件所在路径下创建abc文件夹
# os.mkdir('D:\\abc')  # 就是在指定的绝对路径下创建abc文件夹

# os.mkdir('a/b/c')  # a,b必须提前存在,c不能存在
# os.makedirs(r'a\b\c')  # a,b存在与否都可以,c不能存在

  

不常用的用法

'''
工作目录:os.getcwd()
删除文件:os.romeve('file_path')
删除单层空目录:os.rmdir('dirname')
移除多层空目录:os.removedirs('dirname1/.../dirnamen')
路径分隔符:os.sep
行终止符:os.linesep
文件分隔符:os.pathsep
操作系统名:os.name
操作系统环境变量:os.environ
执行shell脚本:os.system()
'''

  

 

1.8 os.path  系统路径操作

'''
目标大小:os.path.getsize(path)
当前目录(文件夹):os.path.dirname(path) 
上级目录(文件夹):os.path.dirname(os.path.dirname(__file__))
路径拼接:os.path.join(path1[, path2[, ...]])
指定路径是否存在:os.path.exists(path)
'''

  

不常用的用法

'''
是否是文件:os.path.isfile(path)
是否是路径:os.path.isdir(path) 

返回path规范化的绝对路径:os.path.abspath(path)  
最后一级名称:os.path.basename(path)
是否是绝对路径:os.path.isabs(path)
最后存取时间:os.path.getatime(path)
最后修改时间:os.path.getmtime(path)
将path分割成目录和文件名二元组返回:os.path.split(path) 
'''

  

part1_path = os.path.join(BASE_DIR, 'part1')  # => BASE_DIR + os.sep + 'part1'
sys.path.append(part1_path)
part3_path = os.path.join(BASE_DIR, 'part3')
sys.path.append(part3_path)
print(sys.path)

  

1.9 sys  系统

命令行参数List,第一个元素是程序本身路径:sys.argv
退出程序,正常退出时exit(0):sys.exit(n) 
获取Python解释程序的版本信息:sys.version
最大int值:sys.maxsize | sys.maxint
环境变量:sys.path
操作系统平台名称:sys.platform

# 导模块的过程中  .语法左侧必须是文件夹

# 添加指定路径到环境变量中
# sys.path.append(’引用模块的地址') 
# sys.path.insert(索引号, '引用模块的地址') 
sys.path.append(r'F:/1-4 python基础复习') 
sys.path.insert(0,r'F:/1-4 python基础复习')

  

  

1.10 跨文件夹移动文件 (os,os.path模块操作案例)

 
part5

----mm.py

part6

----abc

----os.py(就是下面的代码)

  

# 将part5下的mm.py移动到part6下abc文件夹中


import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)

def move_file(file, folder):
    if not (os.path.exists(file) and os.path.isfile(file)):
        print('文件不存在或非法')
        return False
    if not os.path.exists(folder):
        os.makedirs(folder)
    file_name = os.path.split(file)[1]
    # file_name = os.path.basename(file)
    new_file = os.path.join(folder, file_name)

    with open(file, 'rb') as rf, open(new_file, 'wb') as wf:
        for line in rf:
            wf.write(line)

    os.remove(file)

# 将目标文件夹下的目标文件移动到指定文件夹下
file = os.path.join(BASE_DIR, 'part5', 'mm.py')
folder = os.path.join(BASE_DIR, 'part6', 'abc')
move_file(file, folder)

  

1.11 random 随机数 

'''
(0, 1):random.random()  # 0 到1之间的随机小数
[1, 10]:random.randint(1, 10)  # 0 到10之间的随机整数数  含1和10
[1, 10):random.randrange(1, 10) # 左包又不不包
(1, 10):random.uniform(1, 10)  # 两边不包含 是小数
单例集合随机选择1个:random.choice(item)
单例集合随机选择n个:random.sample(item, n)
洗牌单列集合:random.shuffle(item)
'''

  

1.12 json : 序列化与反序列化

json语言,是一种有语法规范的字符串,是用来存放数据的,主要用来各语言之间的数据交互,最常见与前后端交互
1.就是{}和[]的组合,{}存放双列信息(类比字典) ,[]存放单列信息(类比列表)
2.{}的key必须是字符串,并且用""包裹(双引号)
3.{},[]中的值支持的类型  :dict |list| int |float| bool| str| null

  

序列化          将对象转化为字符串

反序列化      将字符串转化为对象

# 序列化:将对象转换为字符串
#json.dumps():  将 Python 对象序列化 JSON 字符串
# json.dump():  将Python对象序列化为json字符串后写入文件
obj = {'name': 'Owen', "age": 18, 'height': 180, "gender": "男"}
r1 = json.dumps(obj, ensure_ascii=False)  # 取消默认ascii编码,同该文件的编码 utf-8 py3默认,py2规定文件头
print(r1)
# {"name": "Owen", "age": 18, "height": 180, "gender": "男"}


with open('1.txt','w',encoding='utf-8') as wf: # 若没有1.txt会创建
    json.dump(obj,wf,ensure_ascii=False)
# 将转化后的json字符串{"name": "Owen", "age": 18, "height": 180, "gender": "男"}写入1.txt中


# 反序列化:将字符串转换为对象
# json.load()    读取文件中json形式的字符串元素转化为Python对象
# json.loads()   将已编码的 JSON 字符串解码为 Python 对象

json_str = '{"name": "Owen", "age": 18, "height": 180, "gender": "男"}'
r2 = json.loads(json_str, encoding='utf-8')  # 默认跟当前文件被解释器执行的编码走
print(r2, type(r2))

with open('1.txt', 'r', encoding='utf-8') as rf:
    r3 = json.load(rf)
    print(r3, type(r3))

  

1.13 pickle   序列化与反序列化

# 为什么有很多序列化和反序列化模块
# 因为程序中会出现各种各样的对象,如果要将这些对象持久化存储,必须先序列化
# 只有序列化存储后,必须有对应的反序列化,才能保证存储的数据能被重新读取使用

# 什么是序列化:对象 => 字符串
# 为什么序列化:存 或 传
# 为什么要反序列化:再次使用
# 为什么有很多序列化模块:存与取的算法可以多种多样,且要配套

# pickle使用: 二进制的时候 字节操作 import pickle obj = {"name": 'Owen', "age": 18, "height": 180, "gender": "男"} # 序列化 r1 = pickle.dumps(obj) print(r1) with open('2.txt', 'wb') as wf: pickle.dump(obj, wf) # 反序列化 with open('2.txt', 'rb') as rf: data = rf.read() o1 = pickle.loads(data) print(o1, type(o1)) rf.seek(0, 0) # 游标移到开头出现读 o2 = pickle.load(rf) print(o2, type(o2))

  

1.14 shelve  序列化  反序列化 (不常用)

# 将序列化文件操作dump与load进行封装
shv_dic = shelve.open("target_file")  # 注:writeback允许序列化的可变类型,可以直接修改值
# 序列化:存
shv_dic['key1'] = 'value1'
shv_dic['key2'] = 'value2'

# 文件这样的释放
shv_dic.close()

shv_dic = shelve.open("target_file", writeback=True)
# 存 可变类型值
shv_dic['info'] = ['原数据']


# 取 可变类型值,并操作可变类型
# 将内容从文件中取出,在内存中添加, 如果操作文件有writeback=True,会将内存操作记录实时同步到文件
shv_dic['info'].append('新数据')

# 反序列化:取
print(shv_dic['info'])  # ['原数据', '新数据']

shv_dic.close()

  

1.15 hashlib  加密 (重点)

 
# 不可逆加密:没有解密的加密方式 md5
# 解密方式:碰撞解密
# 加密的对象:用于传输的数据(字符串类型数据)

# 一次加密:
# 1.获取加密对象  hashlib.md5() => lock_obj
# 2.添加加密数据  lock_obj.update(b'...') ... lock_obj.update(b'...')
# 3.获取加密结果  lock.hexdigest() => result

lock = hashlib.md5()
res = lock.hexdigest()
print(res)

# 加盐加密
# 1.保证原数据过于简单,通过复杂的盐也可以提高解密难度
# 2.即使被碰撞解密成功,也不能直接识别盐与有效数据
lock_obj = hashlib.md5()
lock_obj.update(b'goodgoodstudy')
lock_obj.update(b'123')
lock_obj.update(b'daydayup')
res = lock_obj.hexdigest()
print(res)


# 了了解:其他算法加密
lock_obj = hashlib.sha3_256(b'1')
print(lock_obj.hexdigest())
lock_obj = hashlib.sha3_512(b'1')
print(lock_obj.hexdigest())

  

1.16 shutil   文件操作

# 基于路径的文件复制:
shutil.copyfile('source_file', 'target_file')

# 基于流的文件复制:
with open('source_file', 'rb') as r, open('target_file', 'wb') as w:
    shutil.copyfileobj(r, w)
    
# 递归删除目标目录
shutil.rmtree('target_folder')

# 文件移动
shutil.move('old_file', 'new_file')

# 文件夹压缩
# file_name:被压缩后形成的文件名  format:压缩的格式  archive_path:要被压缩的文件夹路径
shutil.make_archive('file_name', 'format', 'archive_path')

# 文件夹解压
# unpack_file:被解压文件 unpack_name:解压后的名字 format解压格式
shutil.unpack_archive('unpack_file', 'unpack_name', 'format')

  

1.17 logging日志模块 

logging模块是python提供的用于记录日志的模块

 

日志级别

随着时间的推移,日志记录会非常多,成千上万行,如何快速找到需要的日志记录这就成了问题

解决的方案就是 给日志划分级别

logging模块将日志分为了五个级别,从高到低分别是:

1.debug 调试信息

2.info 常规信息

3.warning 警告信息

4.error 错误信息

5.cretical 严重错误

本质上他们使用数字来表示级别的,从高到低分别是10,20,30,40,50

  

使用

 
import logging
import sys

# logging配置:格式化输出 1)输出的方式  2)输出的格式 3)输出的位置
h1 = logging.StreamHandler()
h2 = logging.FileHandler('d.log')
logging.basicConfig(
    # filename='my.log',
    # filemode='w',
    # stream=sys.stderr,  # 往控制台打印采用具体的输出流
    format='%(asctime)s [%(levelname)s]- %(name)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
    level=logging.DEBUG,  # 10, 代表DEBUG及DEBUG级别以上都能输出
    handlers=[h1, h2]
)

logging.debug("debug")
logging.info("info")
logging.warning("warning")
logging.error("error")
logging.critical("critical")

# 对比sys.stdout | sys.stderr有什么优势
#

  

logging的最低显示级别为warning,对应的数值为30

日志被打印到了控制台

日志输出格式为:级别  日志生成器名称  日志消息

  

1.17-1 自定义日志配置

 
import logging
logging.basicConfig()

"""可用参数
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。 
datefmt:指定日期时间格式。 
level:设置rootlogger(后边会讲解具体概念)的日志级别 
"""

#案例:
logging.basicConfig(
    filename="aaa.log",
    filemode="at",
    datefmt="%Y-%m-%d %H:%M:%S %p",
    format="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s",
    level=10
)

  

1.71-2 logging模块的四个核心角色

1.Logger   日志生成器 产生日志

2.Filter    日志过滤器  过滤日志

3.Handler 日志处理器 对日志进行格式化,并输出到指定位置(控制台或文件)

4.Formater 处理日志的格式


# 1.新建打印者
logger = logging.getLogger("Owen")

# 2.创建句柄:输出的位置
stream_handler = logging.StreamHandler()
a_file_handler = logging.FileHandler('a.log')
b_file_handler = logging.FileHandler('b.log')

# 3.打印者绑定句柄
logger.addHandler(stream_handler)
logger.addHandler(a_file_handler)
logger.addHandler(b_file_handler)

# 4.设置格式
fmt1 = logging.Formatter('%(asctime)s - %(msg)s')
fmt2 = logging.Formatter('%(asctime)s [%(name)s] - %(msg)s')

# 5.为句柄绑定输出格式
stream_handler.setFormatter(fmt1)
a_file_handler.setFormatter(fmt1)
b_file_handler.setFormatter(fmt2)

logger.critical('msg')

  

1.71-3 多输出者

import logging
# 1.创建logger
log1 = logging.getLogger('Owen')
log2 = logging.getLogger('Zero')
r_log = logging

# 2.logger设置级别
log1.setLevel(logging.DEBUG)

# 3.设置句柄
h1 = logging.StreamHandler()

# 4.设置句柄级别:
# 1)系统句柄默认级别warning,
# 2)自定义的句柄级别默认同logger,也可以在logger基础上在加以限制
h1.setLevel(logging.DEBUG)

# 5.logger添加句柄
log1.addHandler(h1)

# log1可以打印DEBUG以上的信息,但往不同位置打印,采用不同句柄的二次级别限制
h2 = logging.FileHandler('c.log')
h2.setLevel(logging.WARNING)
log1.addHandler(h2)


log1.debug('debug')
log1.info('info')
log1.warning('warning')
log1.error('error')
log1.critical('critical')

log2.critical('00000')

r_log.critical('00000')

  

1.71-4  配置文件的使用

# 1.配置
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'o_fmt1': {
            'format': '%(name)s:%(asctime)s - %(message)s'
        },
        'o_fmt2': {
            'format': '%(name)s:%(asctime)s [%(levelname)s] - %(message)s'
        }
    },
    'filters': {},
    'handlers': {
        'o_cmd': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'o_fmt1'
        },
        'o_file': {
            'level': 'WARNING',
            'class': 'logging.handlers.RotatingFileHandler',
            'formatter': 'o_fmt2',
            'filename': r'F:\python8期\课堂内容\day20\代码\part4\logging.log',  # 日志文件
            'maxBytes': 1024*1024*5,  # 日志大小 5M
            'backupCount': 5, #日志文件最大个数
            'encoding': 'utf-8',  # 日志文件的编码
        }
    },
    'loggers': {
        'o_owen': {
            'level': 'DEBUG',
            'handlers': ['o_cmd', 'o_file']
        },
        'o_zero': {
            'level': 'DEBUG',
            'handlers': ['o_file']
        }
    }
}

# 2.加载配置
import logging.config
logging.config.dictConfig(LOGGING_DIC)


# 3.使用
log = logging.getLogger('o_owen')
log.warning('123')

  

1.18  re 模块 

 
'''
正则 : 有语法的字符串 ,用来匹配目标字符串

1:常用于爬虫  
2:判断字符串内容是否满足某种规则  多用于规范用户输入  比如输入手机号  邮箱等
'''

  

元字符描述
\ 将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
^ 代表以什么开头。如果设置了RegExp对象的Multiline属性,也匹配“\n”或“\r”之后的位置。
$ $代表以什么结尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配0到无数个。
+ 匹配1到无数个。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,} n是一个非负整数。匹配n到无数个。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m} 匹配n到m个。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
? 匹配0到1个。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。
? 当该字符紧跟在任何一个其他限制符(,+,?,{n},{n,},{n,m*})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
.点 匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。
   
x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[zf]ood”则匹配“zood”或“food”。
[xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“abc”可以匹配“plain”中的“plin”任一字符。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“a-z”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1”可以匹配“1_23”中的“1”,但不能匹配“21_3”中的“1_”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”
\s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何可见字符。等价于 \f\n\r\t\v。
\w \w == [A_Za-z0-9] 匹配所有大小写和数字的单个字符串 此时汉字当做一个字符来看待
\W \W 就是\w的对立面 匹配所有非大小写数字的单个字符串
\d 匹配单独数字字符。等价于[0-9]。
\D \D就是\d的对立面 匹配所有非数字的单个字符
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\t 匹配一个制表符。等价于\x09和\cI。
( ) 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
(?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
| 将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。
 
 
 
 

1.81-1   匹配单个字符

import re

# 单个字符匹配
'''
re.findall(pattern, string, flags=0)  
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

'pattern':匹配规则   string:需要匹配的字符串 
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

'''

# re.I不区分大小写
res = re.findall(r'a','abc123嘿嘿abcABC',flags=re.I)
print(res)  # ['a', 'a', 'A']

# a|b   a或b单个字符
res = re.findall(r'a|b','abc123嘿嘿abcAB',flags=re.I)
print(res)  # ['a', 'b', 'a', 'b', 'A', 'B']

# [a,b]  或a 或, 或b单个字符  匹配
res = re.findall(r'[a,b]','abc,123嘿嘿abcABC',flags=re.I)
print(res)  # ['a', 'b', ',', 'a', 'b', 'A', 'B']

# [^ab]  非a非b得所有单个字符
res = re.findall(r'[^ab]','abc,123嘿嘿abcABC')
print(res)  #  ['c', ',', '1', '2', '3', '嘿', '嘿', 'c', 'A', 'B', 'C']

# [a-z]匹配所有小写字符  [A-Z]匹配所有大写字母  [0-9]匹配所有数字
res = re.findall(r'[a-z]','abc,123嘿嘿abcABC')
print(res)   #  ['a', 'b', 'c', 'a', 'b', 'c']

res = re.findall(r'[0-9]','abc,123嘿嘿abcABC')
print(res)   # [1,2,3]

# 匹配所有大小写和数字
print(re.findall(r'[a-z]|[A-Z]|[0-9]', 'abc,123嘿嘿abcABC'))
# ['a', 'b', 'c', '1', '2', '3', 'a', 'b', 'c', 'A', 'B', 'C']

# 匹配所有大小写和数字
res = re.findall(r'[a-zA-Z0-9]','abc,123嘿嘿abcABC')
print(res)
# ['a', 'b', 'c', '1', '2', '3', 'a', 'b', 'c', 'A', 'B', 'C']

# \d 匹配单独数字  == [0-9]
res = re.findall(r'\d','abc,1234嘿嘿abcABC')
print(res)  # ['1', '2', '3', '4']

# \D就是\d的对立面  匹配所有非数字的单个字符
res = re.findall(r'\D','abc,1234嘿嘿abcABC')
print(res)
# ['a', 'b', 'c', ',', '嘿', '嘿', 'a', 'b', 'c', 'A', 'B', 'C']

# \w  == [A_Za-z0-9]  匹配所有大小写和数字的单个字符串   此时汉字当做一个字符来看待
print(re.findall(r'\w', 'abc,123嘿[_'))
# ['a', 'b', 'c', '1', '2', '3', '嘿', '_']

# \W  就是\w的对立面  匹配所有非大小写数字的单个字符串
print(re.findall(r'\W', 'abc,123嘿[_'))
#  [',', '[']

# .会匹配所有非\n的单个字符
res = re.findall(r'.','*\_+=\n \r\t')
print(res)  # ['*', '\\', '_', '+', '=', ' ', '\r', '\t']
# python中  匹配时如有只是单个\  匹配出来则是\\


# re.S会让.匹配所有单个字符
res = re.findall(r'.','*\_+=\n \r\t',flags=re.S)
print(res)
# ['*', '\\', '_', '+', '=', '\n', ' ', '\r', '\t']

# 单个汉字 [\u4e00-\u9fa5]
print(re.findall(r'[\u4e00-\u9fa5]', 'abc,123嘿[_'))  # ['嘿']

# \s == [\f\n\r\t\v ] 单个空:空格、制表符、换页符等
print(re.findall(r'\s', '\f\n\r\t\v '))  # ['\x0c', '\n', '\r', '\t', '\x0b', ' ']

  

1.81-2  正则匹配步骤

import re
# 1.将r'\\'的正则语法字符串转换成 正则对象 '\', 用来匹配 '\' 字符的
# 2.拿着转换后的正则对象,来匹配目标字符串
print(re.findall(r'\\', r'a\d\p\\'))  # ['\\', '\\', '\\', '\\']

'''
re.compile(pattern, flags=0)
“编译正则表达式模式,返回模式对象。”
'''

re_obj = re.compile(r'\n')  # 转换成匹配 换行符 的正则对象
res = re_obj.findall('\n')
print(res)  # ['\n']

re_obj = re.compile(r'\\d')  # 转换成匹配 \d 的正则对象
res = re_obj.findall('\d')
print(res)  # ['\\d']

re_obj = re.compile(r'\d')  # 转换成匹配 数字 的正则对象
res = re_obj.findall('\d')  # \d不是数字
print(res)  # []

re_obj = re.compile(r'\\n')  # 转换成匹配 \n 的正则对象
res = re_obj.findall('\n')  # 代表换行,不能被匹配
print(res)  # []
res = re_obj.findall(r'\n')  # 就代表\n,能被匹配
print(res)  # ['\\n']

  

1.81-3 匹配多个匹配

# 多个字符
import re

# 明确个数的数量 {n}
print(re.findall(r'a','aaabbb'))  # ['a', 'a', 'a']
print(re.findall(r'a{2}','aaabbb'))  # ['aa']
print(re.findall(r'ab','aaabbb'))  # ['ab']
print(re.findall(r'a{2}b{2}','aabbababab'))  # ['aabb']
print(re.findall(r'ab{2}','aabbabababa'))  # ['abb']


# {n,}  匹配n到无数个,题中最少匹配abb, 贪婪匹配 abbb 能被匹配为 abb 和 abbb,优先匹配多的
print(re.findall(r'ab{2,}', 'ababbbabbabbbbc'))
# ['abb', 'abbb', 'abbbb']


# {,n} 匹配0到n个  ab{,2} 优先匹配abb  如没有ab也行 还没有a也行
print(re.findall(r'ab{,2}', 'aababbabbbabbbb'))
# ['a','ab','abb','abb','abb']


# {n,m}匹配n到m个,  ab{1,3}  则优先匹配abbb  然后abb 最后ab
print(re.findall(r'ab{1,3}', 'aababbabbbabbbb'))
# ['ab','abb','abbb','abbb']


# 特殊符号的重复
#  *   匹配0到无数个
print(re.findall(r'ab*','aababbabbbabbbb'))
# ['a', 'ab', 'abb', 'abbb', 'abbbb']

# +  匹配1到无数个
print(re.findall(r'ab+','aababbabbbabbbb'))
# ['ab', 'abb', 'abbb', 'abbbb']

# ?  匹配0到1个
print(re.findall(r'ab?','aababbabbbabbbb'))
# ['a', 'ab', 'ab', 'ab', 'ab']

# 需求:匹配所有单词
print(re.findall(r'[a-z]+', 'abc def hello print'))
# ['abc','def','hello','print']

print(re.findall(r'[a-z]+\b', 'abc def hello print')) 
# ['abc', 'def', 'hello', 'print']

# \b代表单词边界,用空格(字符串的结尾也包括)作为匹配规则
print(re.findall(r'[a-z]*c', 'abc def hello print acb zc'))
# ['abc', 'ac', 'zc']

  

1.81-4  多行匹配

# 多行匹配
import re
s = """http://www.baidu.com
https://sina.com.cn
https://youku.com
haam
abchttp://www.oldboy.com
"""
# 需求:拿到url的域名的  baidu , youku

# ^代表以什么开头,$代表以什么结尾,必须结合flags=re.M来完成多行匹配
res = re.findall(r'^http.+com$',s,flags=re.M)
print(res)

  

1.81-5  分组

 
# 分组匹配
import re

url = 'https://www.baidu.com, http://www.youku.com'
# 需求:拿到url的域名的  baidu , youku
res = re.findall(r'www.([a-z]+).com',url)
print(res)


# ()代表分组
# findall匹配,如果匹配规则用有分组语法,只存放分组结果
print(re.findall(r'(www).([a-z]+).com', url))
# [('www', 'baidu'), ('www', 'youku')]

# findall是全文匹配,可以从任意位置开始,匹配多次
# match非全文匹配,必须从头开始匹配,只能匹配一次
# 专门处理分组的方法:分组,分组编号,有名分组,取消分组
# 取消分组: 必须写(),但是()为分组语法,我们只是想通过()将一些数据作为整体,所以()必须,再取消分组即可
# (?:) 取消分组只是作为整体   (?P<名字>) 有名分组


url = 'www.baidu.com,www.youku.com'
res = re.match(r'((?:www).(?P<name>[a-z]+).com)', url)
print(res)
# <re.Match object; span=(0, 13), match='www.baidu.com'>
print(res.group(1))  # www.baidu.com
print(res.group(2))  # baidu
print(res.group('name'))  # baidu

  

1.81-6 拆分和替换

import re

s = 'a b ac def'
print(s.split(' '))  # ['a', 'b', 'ac', 'def']

# 正则拆分
s = 'a b,ac@def'
print(re.split(r'[ ,@]', s))  # ['a', 'b', 'ac', 'def']


s = 'python abc python'
print(re.sub('python', 'Python', s))  # Python abc Python
print(re.sub('python', 'Python', s, count=1))  # Python abc python


# 结合分组可以完成信息的重组与替换
s = 'day a good!!!'  # 'a good good day'
print(re.sub('(day) (a) (good)', r'today is \2 \3 \3 \1', s))

  

 
 
 
 
 

 

 
 
 

 

 

  

 
posted @ 2019-03-17 22:26  犹豫就会拜佛  阅读(163)  评论(0编辑  收藏  举报