16.1、time模块:
1、在python中常用的三种时间表示:
(1)时间戳(timestamp):
通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
(2)格式化的时间字符串;
(3)元组(struct_time):
struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时);
2、范例:
import time
# 导入时间模块
print(time.time())
# 返回当前时间的时间戳
# 1566738002.8696113
print(time.localtime())
print(time.localtime(1473525444.037215))
# 将一个时间戳转换为当前时区的struct_time。如果未传入参数,则传入time.time()。
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=25, tm_hour=21, tm_min=3, tm_sec=45, tm_wday=6, tm_yday=237, tm_isdst=0)
# time.struct_time(tm_year=2016, tm_mon=9, tm_mday=11, tm_hour=0, tm_min=37, tm_sec=24, tm_wday=6, tm_yday=255, tm_isdst=0)
print(time.gmtime())
# 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
# time.struct_time(tm_year=2019, tm_mon=8, tm_mday=25, tm_hour=13, tm_min=8, tm_sec=58, tm_wday=6, tm_yday=237, tm_isdst=0)
print(time.mktime(time.localtime()))
# 将一个struct_time转化为时间戳。
# 1566738706.0
print(time.asctime())
# 把一个表示时间的元组或者struct_time表示为这种形式:'Sun Aug 25 21:12:49 2019'。
# 如果没有参数,将会将time.localtime()作为参数传入。
print(time.ctime())
print(time.ctime(1473525444.037215))
# 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式:'Sun Aug 25 21:18:28 2019'
# 如果没有参数,默认传入time.time()参数
print(time.strftime("%Y-%m-%d %X"))
# 把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格
# 式化的时间字符串。如果未指定时间元组或struct_time,将传入time.localtime()。如果元组中任何一个元素越界,
# ValueError的错误将会被抛出。
# 2019-08-25 21:37:08
print(time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X'))
# 把一个格式化时间字符串转化为struct_time,实际上它和strftime()是逆操作,如果未指定时间字符串的格式,
# format默认为:"%a %b %d %H:%M:%S %Y"。
# time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, tm_wday=3, tm_yday=125, tm_isdst=-1)
time.sleep(2)
# 线程推迟指定的时间运行,单位为秒。
3、不同时间格式相互转化图示:
16.2、random模块:
1、示例:
import random
# 引入random模块
print(random.random())
# 随机取出0<x<1的浮点数
# 0.2398746321065972
print(random.uniform(1, 10))
# 随机取出0<x<10的浮点数
# 1.7549658969860702
print(random.randint(1, 10))
# 随机取出1<=x<=10的整数
print(random.randrange(1, 10))
# 随机取出1<=x<10的整数
print(random.choice([1, '23', [4, 5]]))
# 从可迭代对象中随机取出一个元素
print(random.sample("liuchang",2))
# 从可迭代对象中随机取出n个元素并组成一个列表
item = [1, 3, 5, 7, 9]
random.shuffle(item)
print(item)
# 把一个列表中的所有元素打乱并从新排序
2、随机生成一个5位数的验证码:
import random
def v_code():
code = ''
for i in range(5):
num = random.randint(0, 9)
char = chr(random.randint(65, 90))
add = str(random.choice([num, char]))
code = code + add
return code
print(v_code())
16.3、os模块:
1、os模块是与操作系统交互的一个接口;
2、示例:
import os
# 导入os模块
print(os.path.dirname(os.path.abspath(__file__)))
# 获取当前py脚本执行的目录;
print(os.getcwd())
# 返回python当前工作的目录;注意:并不是当前py脚本执行的目录;
# D:\developer\PythonWorkSpace\python
os.chdir("cal")
# 改变python当的工作目录,相当于shell下cd;
print(os.getcwd())
# D:\developer\PythonWorkSpace\python\cal
print(os.curdir)
# 返回python当前工作的目录: ('.')
print(os.pardir)
# 返回python当前工作的目录的父目录:('..')
print(os.path.abspath(os.curdir))
print(os.path.abspath(os.pardir))
# 获取python工作目录绝对路径的方法
os.makedirs('dir1/dir2')
# 生成多层递归目录,如果目录已经存在则无法进行创建,会报错;
os.removedirs('<目录名>')
# 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此
# 类推,如果目录不为空或指定的目录不存在会报错;
os.mkdir('dir3')
# 生成单级目录,如果目录已经存在则无法进行创建,会报错;
os.rmdir('dir3')
# 删除单级空目录,若目录不为空或指定的目录不存在则无法删除,会报错;
print(os.listdir('dir1'))
# 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
# 如果目录不存在会报错;
os.rename("66.py", "77.py")
# 重命名文件或目录,指定的目录或文件不存在会报错;
os.remove('77.py')
# 删除一个文件,指定的文件不存在会报错;
print(os.stat('77.py'))
# 获取文件或目录信息,指定的文件或目录不存在会报错;
# os.stat_result(st_mode=33206, st_ino=15762598695814373, st_dev=584358891, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1566750074, st_mtime=1566750074, st_ctime=1566750074)
# atime(access time):访问时间,文件中的数据最后被访问的时间;
# mtime(modify time):修改时间,文件内容被修改的最后时间;
# ctime(change time):变化时间,文件的元数据发生变化,比如权限,所有者等;
print(os.sep)
# 输出当前平台使用的路径分隔符,win下为"\", Linux下为"/";
print(os.linesep)
# 输出当前平台使用的换行符,win下为"\r\n", Linux下为"\n";
print(os.pathsep)
# 输出当前平台用的于分割文件路径的字符串,win下为";", Linux下为":";
print(os.name)
# 输出字符串指示当前使用平台,win->'nt',Linux->'posix';
os.system("cd c:")
# 运行shell命令,直接显示;
print(os.environ)
# 获取系统环境变量;
print(os.path.abspath("cal/cal.py"))
# 返回path规范化的绝对路径;
# D:\developer\PythonWorkSpace\python\cal\cal.py
print(os.path.split(r"D:\developer\PythonWorkSpace\python\cal\cal.py"))
# 将path分割成目录和文件名二元组返回;
# ('D:\\developer\\PythonWorkSpace\\python\\cal', 'cal.py')
print(os.path.dirname(r"D:\developer\PythonWorkSpace\python\cal\cal.py"))
# 返回path的目录,其实就是os.path.split(path)的第一个元素;
# D:\developer\PythonWorkSpace\python\cal
print(os.path.basename(r"D:\developer\PythonWorkSpace\python\cal\cal.py"))
# 返回path最后的文件名,如果path以/或\结尾,那么就会返回空值,即os.path.split(path)的第二个元素;
print(os.path.exists(r"D:\developer\PythonWorkSpace\python\cal\cal.py"))
# 如果path存在,返回True;如果path不存在,返回False;
print(os.path.isabs(r"D:\developer\PythonWorkSpace\python\cal\cal.py"))
# 如果path是绝对路径,返回True,否则返回False;
print(os.path.isfile("77.py"))
# 如果path是一个存在的文件,返回True。否则返回False
print(os.path.isdir("cal"))
# 如果path是一个存在的目录,返回True,否则返回False;
print(os.path.getatime("77.py"))
# 返回path所指向的文件或者目录的最后存取时间,如果指定的文件不存在会报错;
print(os.path.getmtime("77.py"))
# 返回path所指向的文件或者目录的最后修改时间,如果指定的文件不存在会报错;
16.4、sys模块:
1、示例:
import sys
# 引入sys模块
print(sys.argv)
# 命令行参数List,第一个元素是程序本身路径;
# ['D:/developer/PythonWorkSpace/python/test01.py']
sys.exit(0)
# 退出程序,正常退出时exit(0),非正常退出为除0之外整数;
# Process finished with exit code 0
print(sys.version)
# 获取Python解释程序的版本信息
# 3.7.0b3 (v3.7.0b3:4e7efa9c6f, Mar 29 2018, 18:42:04) [MSC v.1913 64 bit (AMD64)]
print(sys.maxsize)
# 最大的Int值
# 9223372036854775807
print(sys.path)
# 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值;
print(sys.platform)
# 返回操作系统平台名称
# win32
2、进度条案例:
import sys, time
for i in range(10):
sys.stdout.write('#')
# 使用sys的stdout标准输出功能将想要的字符串输出到屏幕上;
time.sleep(1)
sys.stdout.flush()
# 输出后立即刷新,目的是不对输出的字符串进行缓存,直接输出到屏幕上,创造动态输出的效果;
16.5、序列化模块:
1、什么是序列化:
(1)用eval(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其
他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
(3)序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
(4)反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
2、JSON:
(1)说明:
1)如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示
出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以
直接在Web页面中读取,非常方便;
2)json能序列化的对象只是Python中基础数据类型;
3)json序列化后的数据是文本类型(记事本打开文件后或者print打印后,你也能看懂其中的内容);
4)json需要的存储空间较小;
5)json表示的对象就是标准的JavaScript语言的对象,JSON和PYTHON内置的数据类型对应如下:
(2)示例:
1)序列化:
import json
dic = {'name': '陈奕迅', 'age': 23, 'sex': '男'}
print(type(dic))
# <class 'dict'>
j = json.dumps(dic,ensure_ascii=False)
# ensure_ascii为True的时,所有非ASCII码字符显示为\uXXXX序列,
# 只需在dump时将ensure_ascii设置为False即可,此时存入json的
# 中文即可正常显示;
print(type(j))
# <class 'str'>
f = open('序列化对象', 'w',encoding='utf8')
f.write(j)
# 等价于json.dump(dic,f)
f.close()
"""
输出的内容:
{'name': '陈奕迅', 'age': 23, 'sex': '男'}
"""
2)反序列化:
import json
f = open('序列化对象','r',encoding='utf8')
data = json.loads(f.read())
print(data)
"""
输出的内容:
{'name': '陈奕迅', 'age': 23, 'sex': '男'}
"""
3)注意:
import json
# dct='{'1':111}'
# json 不认单引号
# dct=str({"1":111})
# 报错,因为生成的数据还是单引号:'{'1': 111}'
dct = '{"1":111}'
print(json.loads(dct))
# 无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
# json外层是单引号,内层字符串用双引号
3、PICKLE:
(1)说明:
1)Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用
Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
2)pickle能序列化Python中所有的数据类型;
3)pickle序列化后数据是二进制流数据(记事本打开后或者print打印后就完全看不懂里面的内容了);
4)pickle需要的存储空间较大;
(2)示例:
1)序列化:
import pickle
dic = {'name': '陈奕旭', 'age': 23, 'sex': '男'}
print(type(dic))
# <class 'dict'>
j = pickle.dumps(dic)
# protocol:序列化协议,0表示ascii协议,ascii码表示,1表示老的二进制协议,2表示新二进制协议,默认为0;
print(type(j))
# <class 'bytes'>
f = open('序列化对象_pickle', 'wb')
# 注意是w是写入str,wb是写入bytes,j是'bytes'
f.write(j)
# 等价于pickle.dump(dic,f)
f.close()
"""
输出的内容:
�}q (X nameqX 陈奕旭qX ageqKX sexqX 男qu.
"""
2)反序列化:
import pickle
f = open('序列化对象_pickle', 'rb')
data = pickle.loads(f.read())
print(data)
"""
输出的内容:
{'name': '陈奕迅', 'age': 23, 'sex': '男'}
"""
16.6、configparser模块:
1、常用配置文件:
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes
[bitbucket.org]
user = hg
[topsecret.server.com]
host port = 50022
forwardx11 = no
2、生成配置文件:
import configparser
# 引入configparser模块
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9'}
config['DEFAULT']['ForwardX11'] = 'yes'
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022'
topsecret['ForwardX11'] = 'no'
with open('example.ini', 'w',encoding='utf8') as configfile:
config.write(configfile)
3、配置文件的查操作:
import configparser
config = configparser.ConfigParser()
config.read('example.ini',encoding='utf8')
print(config.sections())
# 查看所有除[DEFAULT]配置模块的模块
# ['bitbucket.org', 'topsecret.server.com']
print('bytebong.com' in config)
# 查看 bytebong.com 模块是否在配置文件中
# False
print(config['bitbucket.org']['User'])
# 查看某个模块下指定key对应的value
# hg
print(config['DEFAULT']['Compression'])
# yes
print(config['topsecret.server.com']['ForwardX11'])
# no
for key in config['bitbucket.org']:
print(key)
# 迭代某个模块下面所有配置项key,因为DEFAULT模块是通用的配置,
# 所以所有的模块都下默认都会存在DEFAULT的配置项
# user
# serveraliveinterval
# compression
# compressionlevel
# forwardx11
print(config.options('bitbucket.org'))
# 查看某个模块下所有的key,包括DEFAULT模块
# ['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
print(config.items('bitbucket.org'))
# 查看某个模块下所有的key及对应的value,包括DEFAULT模块
# [('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
print(config.get('bitbucket.org', 'compression'))
# 查看某个模块下指定key对应的value
# yes
4、配置文件的增删改操作:
import configparser
config = configparser.ConfigParser()
config.read('example.ini',encoding='utf8')
if 'LC' not in config:
config.add_section('LC')
# 增加模块,如果模块存已经存在会报错
config['LC']['wowo']='lc'
config.set('LC','wowo1','lc1')
# 给模块(如果模块不存在会报错)增加key value 键值对(如果存在会覆盖)
config.remove_option('LC','wowo1')
# 移除某个模块下指定配置项的key(如果模块不存在会报错,key不存在不会报错)
# config.remove_section('LC')
# 移除模块,如果模块不存在不会报错
with open('example.ini', "w", encoding='utf8') as f:
config.write(f)
# 打开文件的模式必须为'w'模式,原理是对配置文件修改后再覆盖
16.7、hashlib模块:
1、用于加密相关的操作,python3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512,MD5 算法
只能对字符串进行加密不能反解密;
2、示例:
import hashlib
m = hashlib.md5()
m.update('lc'.encode('utf8'))
print(m.hexdigest())
# 196accbcf32b0a8e6bef92e1a37d0fc0
m2=hashlib.sha256()
m2.update('lc'.encode('utf8'))
print(m2.hexdigest())
# ef07b359570add31929a5422d400b16c7c84e35644cb2e84b142f0710973e2a8
m3 = hashlib.md5('aojklmnw'.encode('utf8'))
m3.update('lc'.encode('utf8'))
print(m3.hexdigest())
# 以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。
# 所以,有必要对加密算法中添加自定义key再来做加密,其实质是对"aojklmnwlc"进行加密;
# f881b9819ac9262c99ef4ff5eff8b842
# python还有一个hmac模块,它内部为我们创建key和内容后进行处理,然后再加密:
import hmac
h = hmac.new('aojklmnw'.encode('utf8'))
h.update('lc'.encode('utf8'))
print(h.hexdigest())
# ecd93864d1caaeef87e33e4631e69426
16.8、logging模块:
1、简单配置:
import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
"""
控制台输出:
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
"""
# 可见,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置
# 为WARNING(日志级别等级CRITICAL>ERROR>WARNING>INFO>DEBUG>NOTSET,只有日志等级大于或等于设置的日志级别的日志才会被
# 输出),默认的日志格式为"日志级别:Logger名称:用户输出消息"。
2、通过"logging.basicConfig()"灵活配置日志级别,日志格式,输出位置:
import logging
file=open('test.log','a',encoding='utf8')
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
stream=file)
logging.debug('debug message天空')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
# 在文件中查看输出:
# Mon, 26 Aug 2019 23:24:29 test01.py[line:14] DEBUG debug message天空
# Mon, 26 Aug 2019 23:24:29 test01.py[line:15] INFO info message
# Mon, 26 Aug 2019 23:24:29 test01.py[line:16] WARNING warning message
# Mon, 26 Aug 2019 23:24:29 test01.py[line:17] ERROR error message
# Mon, 26 Aug 2019 23:24:29 test01.py[line:18] CRITICAL critical message
# 可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
# filename:指定日志存储的文件位置。
# filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
# format:指定日志显示格式。
# datefmt:指定日期时间格式。
# level:设置日志级别。
# stream:用指定的stream创建日志存储文件位置,若同时列出了filename和stream两个参数,则stream参数会被忽略。
# format参数中可能用到的格式化参数有:
# %(name)s:Logger的名字
# %(levelno)s:数字形式的日志级别
# %(levelname)s:文本形式的日志级别
# %(pathname)s:调用日志输出函数的模块的完整路径名,可能没有
# %(filename)s:调用日志输出函数的模块的文件名
# %(module)s:调用日志输出函数的模块名
# %(funcName)s:调用日志输出函数的函数名
# %(lineno)d:调用日志输出函数的语句所在的代码行
# %(created)f:当前时间,用UNIX标准的表示时间的浮点数表示
# %(relativeCreated)d:输出日志信息时的,自Logger创建以来的毫秒数
# %(asctime)s:字符串形式的当前时间。默认格式是"2019-08-27 00:01:13,655",逗号后面是毫秒
# %(thread)d:线程ID,可能没有
# %(threadName)s:线程名,可能没有
# %(process)d:进程ID,可能没有
# %(message)s:用户输出的消息
3、通过logger对象灵活配置日志:
(1)说明:上述几个例子中我们了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),
logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)
这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)。
(2)配置:
import logging
logger = logging.getLogger('lc')
# 创建一个logger对象,lc 是logger名,标识唯一logger实例,默认是root
logger.setLevel(logging.WARNING)
# 设置的日志的级别,用数字表示,默认是'WARNING'级别;
# 日志级别DEBUG<INFO<WARNING<ERROR<CRITICAL
# 只有日志等级大于或等于设置的日志级别的日志才会被输出
fh = logging.FileHandler('test.log','w',encoding='utf8')
# 创建一个handler对象,用于写入日志文件,默认模式为"a"
ch = logging.StreamHandler()
# 再创建一个handler对象,用于输出到控制台
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 设置日志格式
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 为日志文件和输出到控制台的日志设置格式
logger.addHandler(fh)
logger.addHandler(ch)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message,天空')
logger.error('logger error message')
logger.critical('logger critical message')
# 在文件或控制台上查看输出内容如下:
# 2019-08-27 14:45:32,463 - lc - WARNING - logger warning message,天空
# 2019-08-27 14:45:32,464 - lc - ERROR - logger error message
# 2019-08-27 14:45:32,464 - lc - CRITICAL - logger critical message
# logging库提供了多个组件:Logger、Handler、Filter、Formatter,Logger对象提
# 供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤
# 日志信息的方法,Formatter指定日志显示格式。
# Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取
# 则自动创建并使用 root Logger),logger = logging.getLogger(),返回一个默认
# 的 Logger 也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
# 只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,
# 也即name与Logger实例一一对应,如果设置了多个实例 name 相同,那么logger对象设置日志级别会
# 遵从最后设置的日志级别。
# 如果logging.getLogger(name)中名称参数name不同则logger实例之间的日志级别互不影响
# 实例1:name1=logging.getLogger(name)
# 实例2:name2=logging.getLogger(name.name1)
# 子实例会依次将自己的实例日志交到父级日志中
# Filter 限制只有满足过滤规则的日志才会输出,比如我们定义了filter = logging.Filter('a.b.c'),
# 并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带 a.b.c 前缀的Logger
# 才能输出其日志。
# filter = logging.Filter('lc')
# logger.addFilter(filter)
# 这是只对logger这个对象进行筛选
# 如果想对所有的对象进行筛选,则:
# filter = logging.Filter('lc')
# fh.addFilter(filter)
# ch.addFilter(filter)
# 这样,所有添加fh或者ch的logger对象都会进行筛选。
16.9、re模块(正则表达式):
1、说明:
就其本质而言,正则表达式是一种小型的、高度专业化的编程语言,在Python中它是内嵌的,
通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
2、匹配规则:
# .:匹配任意一个字符
# ^:匹配以什么字符或字符串开头
# $:匹配以什么字符或字符串结尾
# *:匹配字符重复出现0到无穷次
# +:匹配字符重复出现1到无穷次
# ?:匹配字符重复出现0到1次
# {}:根据需求匹配字符重复出现的次数
# []:匹配中括号中出现的任何字符(或运算),在字符集里有功能的符号: - ^ \
# |:匹配竖线两边出现的字符或字符串(或运算)
# ():分组运算
# \:转义字符:
# 反斜杠后边跟元字符去除特殊功能, 比如\.
# 反斜杠后边跟普通字符实现特殊功能, 比如\d
# \d:匹配任何十进制数;它相当于类[0 - 9]
# \D:匹配任何非数字字符;它相当于类[^ 0 - 9]
# \s:匹配任何空白字符;它相当于类[\t\n\r\f\v]
# \S:匹配任何非空白字符;它相当于类[^ \t\n\r\f\v]
# \w:匹配任何字母数字字符;它相当于类[a - zA - Z0 - 9_]
# \W:匹配任何非字母数字字符;它相当于类[^ a - zA - Z0 - 9_]
# \b:匹配一个特殊字符边界,比如空格 , & , # 等
3、示例:
import re
ret = re.findall('a..in', 'helloalvin')
print(ret)
# ['alvin']
ret = re.findall('^a...n', 'alvinhelloawwwn')
print(ret)
# ['alvin']
ret = re.findall('a...n$', 'alvinhelloawwwn')
print(ret)
# ['awwwn']
ret = re.findall('abc*', 'abcccc')
print(ret)
# 贪婪匹配[0,+oo]
# ['abcccc']
ret = re.findall('abc+', 'abccc')
print(ret)
# 贪婪匹配[1,+oo]
# ['abccc']
ret = re.findall('abc?', 'abccc')
print(ret)
# [0,1]
# ['abc']
ret = re.findall('abc{1,4}', 'abccc')
print(ret)
# ['abccc'] 贪婪匹配
ret = re.findall('abc*?', 'abcccccc')
print(ret)
# 注意:前面的 *、+、? 都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
# ['ab']
ret = re.findall('a[bc]d', 'acd')
print(ret)
# 在字符集里有功能的符号: - ^ \
# ['acd']
ret = re.findall('[a-z]', 'acd')
print(ret)
# ['a', 'c', 'd']
ret = re.findall('[1-9]', '45dha3')
print(ret)
# ['4', '5', '3']
ret = re.findall('[.*+]', 'a.cd+')
print(ret)
# ['.', '+']
ret = re.findall('[^ab]', '45bdha3')
print(ret)
# ['4', '5', 'd', 'h', '3']
ret = re.findall('[\d]', '45bdha3')
print(ret)
# ['4', '5', '3']
# 与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。
# 假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜
# 杠"\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在
# 正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,有了原
# 生字符串,再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
ret = re.findall('I\b', 'I am LIST')
print(ret)
# []
ret = re.findall('I\\b', 'I am LIST')
print(ret)
# ['I']
ret = re.findall(r'I\b', 'I am LIST')
print(ret)
# ['I']
ret = re.findall('c\\\\l', 'abc\le')
print(ret)
# ['c\\l']
ret = re.findall(r'c\\l', 'abc\le')
print(ret)
# ['c\\l']
m = re.findall('\bblow', 'blow')
print(m)
# []
m = re.findall(r'\bblow', 'blow')
print(m)
# ['blow']
m = re.findall('a|d', 'add')
print(m)
# ['a', 'd', 'd']
ret = re.findall('(ad)', 'adad2ad')
print(ret)
# ['ad', 'ad', 'ad']
ret = re.findall('(ad)+', 'adad2ad')
print(ret)
# ['ad', 'ad']
ret = re.findall('(?:ad)+', 'adad2ad')
print(ret)
# ['adad', 'ad']
ret = re.search('(ad)', 'adad2ad')
print(ret.group())
# ad
ret = re.search('(ad)+', 'adad2ad')
print(ret.group())
# adad
ret = re.search('(?:ad)+', 'adad2ad')
print(ret.group())
# adad
ret = re.findall('www.(baidu|lc).com', 'www.lc.com')
print(ret)
# ['lc']
# 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
ret = re.findall('www.(?:baidu|lc).com', 'www.lc.com')
print(ret)
# ['www.lc.com']
ret = re.findall('(?:\d{2})/(?:\w{3})', '23/com')
print(ret)
# ['23/com']
print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>", "<h1>hello</h1><h2>hello</h2>"))
# ['h1', 'h2']
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>", "<h1>hello</h1><h2>hello</h2>").group())
# <h1>hello</h1>
print(re.search(r"<(\w+)>\w+</\1>", "<h1>hello</h1><h2>hello</h2>").group())
# <h1>hello</h1>
ret=re.findall('a', 'alvin yuan')
print(ret)
# 返回所有满足匹配条件的结果,放在列表里
# ['a', 'a']
ret=re.search('a', 'alvin yuan').group()
print(ret)
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
# a
ret = re.search('(?P<id>\d{2})/(?P<name>\w{3})', '23/com')
print(ret.group())
# 23/com
print(ret.group('id'))
# 23
ret = re.search('(ab)|\d', 'rabhdg8sd')
print(ret.group())
# ab
ret=re.match('a', 'abc').group()
print(ret)
# 同search,不过尽在字符串开始处进行匹配,如果在字符串开头匹配不到会报错
# a
ret = re.split('[ab]', 'abcd')
print(ret)
# 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
# ['', '', 'cd']
ret = re.sub('\d', 'abc', 'alvin58yuan6', 1)
print(ret)
# 把字符串中前1个数字替换为'abc'
# alvinabc8yuan6
ret = re.subn('\d', 'abc', 'alvin58yuan6',2)
print(ret)
# 把字符串中前2个数字替换为'abc'并显示替换的个数
# ('alvinabcabcyuan6', 2)
ret = re.subn('\d', 'abc', 'alvin58yuan6')
# 把字符串中所有数字替换为'abc'并显示替换的个数
print(ret)
# ('alvinabcabcyuanabc', 3)
obj = re.compile('\d{3}')
ret = obj.search('abc123eeee456')
print(ret.group())
# 123
ret = re.finditer('\d', 'ds3sy4784a')
print(ret)
# <callable_iterator object at 0x10195f940>
print(next(ret).group())
print(next(ret).group())
# 3
# 4
ret = re.findall("-?\d+\.\d*|(-?\d+)", "1-2*(60+(-40.35/5)-(-4*3))")
ret.remove("")
print(ret)
# 匹配出所有的整数
# ['1', '-2', '60', '5', '-4', '3']
16.10、xxx模块: