7 python常用模块介绍 --time datetime calendar os sys random json pickle shelve hashlib shutil logging re
* 模块定义:一系列功能的集合体 * 模块使用: import导入模块 或者 from ... import... 导入模块 * 模块分类:内置模块 自定义模块 第三方模块 * 模块加载顺序: 内存>内置>sys.path(环境变量中的路径时逐一加载的) * 模块起别名: import 模块名 as 别名
1.一个py文件作为自执行文件,__name__变量的值为 '__main__' if __name__ == '__main__': # 自执行的逻辑 => 因为在文件作为模块使用时 __name__为文件名,不满足条件 pass 2.一个py文件作为模块被导入执行,__name__变量的值为 '文件(模块)名' 此时被其他使用
一系列模块的集合体,用文件件来管理一系列有联系的功能的模块,该文件夹称之为包,文件夹名就是包名
包的文件夹中一定存在一个__init__.py文件文件
1 产生一个全局名称空间提供给包使用 此名称空间就是包的名称空间 2 管理包 包可以直接点出来模块使用
# 导包完成的三件事 # 1)编译形成包中__init__.py文件的pyc文件 # 2)执行__init__.py文件,形成一个全局名称空间,将__init__.py文件中所有名字存放其中,该名称空间就代表包的名称空间 # 3)在导包的文件中,产生一个与包名相同的名字,指向包的名称空间(__init__.py文件的全局名称空间)
# 在包中采用相对导入管理模块或模块中的名字 # 在包的__init__.py文件或是包中任意一个模块中 # . 代表当前文件所在目录 # .. 代表当前文件所在目录的上一级目录 # 注:.语法不能出包,因为包外的文件都能自执行,但拥有.开头导入的文件不能自执行
''' 1.调研 2.需求分析 3.架构师完成项目demo,完成项目架构 4.分工 5.写代码 6.白盒黑盒测试 7.项目审核发布 => 项目 -> 产品 ''' ''' bin: 可执行文件,入口,入口也可以放在项目根目录下 core: 核心代码 db:数据库相关文件 interface:接口 lib:包、模块、第三方文件夹 log:日志 setting:配置 static:静态文件 '''
""" 时间戳(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)
""" 当前时间:datetime.datetime.now() 昨天:datetime.datetime.now() + datetime.timedelta(days=-1) 修改时间:datetime_obj.replace([...]) 格式化时间戳:datetime.date.fromtimestamp(timestamp) """
""" 判断闰年: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))
生成单级目录: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() '''
''' 目标大小: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)
命令行参数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基础复习')
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)
''' (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) '''
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))
# 为什么有很多序列化和反序列化模块 # 因为程序中会出现各种各样的对象,如果要将这些对象持久化存储,必须先序列化 # 只有序列化存储后,必须有对应的反序列化,才能保证存储的数据能被重新读取使用 # 什么是序列化:对象 => 字符串 # 为什么序列化:存 或 传 # 为什么要反序列化:再次使用 # 为什么有很多序列化模块:存与取的算法可以多种多样,且要配套
# 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))
# 将序列化文件操作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()
# 不可逆加密:没有解密的加密方式 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())
# 基于路径的文件复制: 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')
随着时间的推移,日志记录会非常多,成千上万行,如何快速找到需要的日志记录这就成了问题 解决的方案就是 给日志划分级别 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 日志被打印到了控制台 日志输出格式为:级别 日志生成器名称 日志消息
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.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')
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.配置 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:常用于爬虫 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."。注意:这个元字符不是所有的软件都支持的。 |
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', ' ']
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']
# 多个字符 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']
# 多行匹配 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)
# 分组匹配 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
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))