常用模块
一、time模块
1、time模块中表示时间的格式:
(1)timestamp时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量
(2)format time 格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。
(3)struct_time时间元组,共有九个元素组。如下表:
索引 | 属性 | 值 |
0 | tm_year(年) | 如2019 |
1 | tm_mon(月) | 1--2 |
2 | tm_day(日) | 1--31 |
3 | tm_hour(时) | 0--23 |
4 | tm_min(分) | 0--60 |
5 | tm_sec(秒) | 0--60 |
6 | tm_wday(weekday) | 0--6(0表示周日) |
7 | tm_yday(一年中的第几天) | 1--366 |
8 | tm_isdst(是否是夏令时) | 默认为-1 |
2、时间格式相互转换:
3、time模块语法
(1)获取struct_time时间元组
data = time.time()
a = time.localtime(data) # 将一个时间戳转换为当前时区的struct_time。()中参数未提供,则以当前时间为准。
b = time.gmtime(data) # 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
print(a)
print(b)
# a的打印结果:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=23, tm_hour=21, tm_min=32, tm_sec=32, tm_wday=5, tm_yday=54, tm_isdst=0)
# b的打印结果:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=23, tm_hour=13, tm_min=32, tm_sec=32, tm_wday=5, tm_yday=54, tm_isdst=0)
由上面两种打印结果来看time.localtime()和time.gmtime()两种方式获取的时间元组结果可能不一样,因为localtime时获取时间元组是按照当前所处的时区来计算的,而gmtime是按照0时区来计算的,因而要根据需要来选择哪种获取那个时区时间元组.
(2)获取时间戳
time_tuple = time.localtime()
a = time.time() # 获取当地当前的时间戳
b = time.mktime(time_tuple) # 讲一个时间元组转换成时间戳
print(a) # 打印结果:1550929461.7366028
print(b) # 打印结果:1550929461.0
上述结果说明用time.time() 获取的时间戳,其精度可以达到毫秒级,而time.mktime()只能精确到秒。在使用time.time()获取时间戳时()里面必须为空,如果不为空则会报错,并且time.time(None)此种用法也会报错。而用time.mktime(tuple) 是将一个时间元组转换成时间戳,因而()里面不能为空,必须填一个时间元组,不填或者tuple=None程序都会报错。
(3)时间元组与时间戳相互转换
time_tuple = time.localtime() # 时间元组
data = time.time() # 时间戳
# 时间元组转换成时间戳
a = time.mktime(time_tuple)
# 时间戳转换成时间元组
b = time.localtime(data)
print(a)
print(b)
(4)时间元组与时间字符串相互转换
time_str = '2019-2-23 22:03:00' # 时间字符串
time_tuple = time.localtime() # 时间元组
# 时间元组转换成时间字符串
a = time.strftime('%Y-%m-%d %H:%M:%S',time_tuple)
# 时间字符串转换成时间元组
b = time.strptime(time_str,'%Y-%m-%d %H:%M:%S')
print(a)
print(b)
(5)time模块其他语法
# 英文显示时间字符串
c = time.asctime(time_tuple)
d = time.asctime()
print(c) # 结果:Sat Feb 23 22:17:08 2019
print(d) # 结果:Sat Feb 23 22:17:08 2019
# 将线程推迟指定的时间运行,单位为秒
befor = time.time()
f = time.sleep(5) # 将下段代码执行时间推迟5秒后执行
now = time.time()
print(befor) # 结果:1550931428.376828
print(now) # 结果:1550931433.376828
(6)字符串转时间格式对应表
索引 | 符号 | 意义 |
0 | %y | 两位数的年份表示(00-99) |
1 | %Y | 四位数的年份表示(000-9999) |
2 | %m | 月份(01-12) |
3 | %d | 月内中的一天(0-31) |
4 | %H | 24小时制小时数(0-23 |
5 | %I | 12小时制小时数(01-12) |
6 | %M | 分钟数(00=59) |
7 | %S | 秒(00-59) |
8 | %a | 本地简化星期名称 |
9 | %A | 本地完整星期名称 |
10 | %b | 本地简化的月份名称 |
11 | %B | 本地完整的月份名称 |
12 | %c | 本地相应的日期表示和时间表示 |
13 | %j | 年内的一天(001-366) |
14 | %p | 本地A.M.或P.M.的等价符 |
15 | %U | 一年中的星期数(00-53)星期天为星期的开始 |
16 | %w | 星期(0-6),星期天为星期的开始 |
17 | %W | 一年中的星期数(00-53)星期一为星期的开始 |
18 | %x | 本地相应的日期表示 |
19 | %X | 本地相应的时间表示 |
20 | %Z | 当前时区的名称 |
21 | %% | %号本身 |
注意:时间字符串和成时间戳相互转换时,必须要先转换成时间元组
二、datetime模块
(1)datetime.date:表示日期的类。常用的属性有year, month, day;只关注日期
import datetime
# 获取当前日期
a = datetime.date.today()
# 时间替换
b = datetime.date.replace(a,year=1,month=2,day=3)
# 转换成时间字符串
c = datetime.date.strftime(a,'%y-%m-%d')
# 转换成时间元组
d = datetime.date.timetuple(a)
print(a) # 结果:2019-02-23
print(b) # 结果:0001-02-03
print(c) # 结果:19-02-23
print(d) #结果:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=23, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=54, tm_isdst=-1)
(2)datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond。只关注时间
import datetime
da = datetime.time(19,2,23) # 分别代表时,分,秒
a = datetime.time.strftime(da,'%H:%M:%S')
print(a) # 结果:19:02:23
(3)datetime.datetime:表示日期时间,同时又日期和时间
import datetime
# 获取当前时间,精确到毫秒
da = datetime.datetime.now()
# 时间替换
a = datetime.datetime.replace(da,year=2000,month=12,day=23,hour=20,minute=45,microsecond=555)
print(da) # 结果:2019-02-23 23:25:39.935206
print(a) # 结果:2000-12-23 20:45:39.000555
(4)datetime.timedelta:表示时间间隔,即两个时间点之间的长度。可以进行时间运算
import datetime
# 获取当前时间,精确到毫秒
da = datetime.datetime.now()
# 加减天数
a = da + datetime.timedelta(-1)
# 加减天数,小时和毫秒
b = da - datetime.timedelta(1,hours=2,microseconds=5)
print(da) #结果:2019-02-23 23:33:57.040902
print(a) #结果:2019-02-22 23:33:57.040902
print(b) #结果:2019-02-22 21:33:57.040897
(5)datetime.tzinfo:与时区有关的相关信息。
三、random模块
import random
import string
#取1-100间的随机数,包含100
a = random.randint(1,100)
print(a)
print(random.randint(1,100))
#取1-100间的随机数,不包含100
b = random.randrange(1,100)
print(b)
#从字符串里随意返回一个字符
c = random.choice('adjhfnbxh12wyt')
print(c)
print(random.choice('adjhfnbxh12wyt'))
#从字符串里随意返回指定数量的字符,以列表方式返回
d = random.sample('adjhfnbxh12wyt',3)
print(random.sample('adjhfnbxh12wyt',3)) # 随机结果:['h', '1', 'j']
print(random.sample('adjhfnbxh12wyt',2)) # 随机结果:['1', 't']
#生成随机验证码
s = string.ascii_lowercase + string.digits #生成小写字母和数字组合的字符串
print(s)
''.join(random.sample(s,6)) #生成6位随机验证码
print(''.join(random.sample(s,6)) )
print(''.join(random.sample(s,6)) )
print(''.join(random.sample(s,6)) )
#洗牌,输出列表
x = list(range(20))
print(x)
random.shuffle(x)
print(x)
四、OS模块
os模块是与操作系统交互的一个接口
1.不含path的命令
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir(“dirname”) 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: (’.’)
os.pardir 获取当前目录的父目录字符串名:(’…’)
os.makedirs(‘dirname1/dirname2’) 可生成多层递归目录
os.removedirs(‘dirname1’) 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推,直至非空目录
os.mkdir(‘dirname’) 生成单级目录;相当于shell中mkdir dirname
os.rmdir(‘dirname’) 删除单级空目录(最后一层目录),若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir(‘dirname’) 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename(“oldname”,“newname”) 重命名文件/目录
os.stat(‘path/filename’) 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->‘nt’; Linux->‘posix’
os.system(“bash command”) 运行shell命令,直接显示
os.popen("bash command) 运行shell命令,获取执行结果
os.environ 获取系统环境变量
2.含path的命令
os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, …]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小
五、sys模块
sys模块是与python解释器交互的一个接口。
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdout.write(‘please:’) #标准输出 , 引出进度条的例子, 注,在py3上不行,可以用print代替
val = sys.stdin.readline()[:-1] #标准输入
sys.getrecursionlimit() #获取最大递归层数
sys.setrecursionlimit(1200) #设置最大递归层数
sys.getdefaultencoding() #获取解释器默认编码
sys.getfilesystemencoding #获取内存数据存到文件里的默认编码
六、序列化
序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes。
序列化目的:
1、以某种存储形式使自定义对象持久化;
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性
pickle模块
pickle是python中独有的序列化模块,是指不能和其他编程语言的序列化进行交互,因为pickle将数据对象转化为bytes
pickle模块提供了四个功能:dumps、dump、loads、load。
dumps和dump都是进行序列化,而loads和load则是反序列化。
dumps将所传入的变量的值序列化为一个bytes,然后,就可以将这个bytes写入磁盘或者进行传输。
import pickle
list = [1,2,3,'d']
str1 = pickle._dumps(list)
print(str1) # 结果:b'\x80\x03]q\x00(K\x01K\x02K\x03X\x01\x00\x00\x00dq\x01e.'
lis = pickle.loads(str1)
print(lis) # 结果:[1,2,3,'d']
而dump则更加一步到位,在dump中可以传入两个参数,一个为需要序列化的变量,另一个为需要写入的文件。
import pickle
list = [1,2,3,'d']
data = {'k1':123,'k2':'Hello'}
f = open('dump.pkl','wb')
str_dumps = pickle.dump(list,f)
f.close()
f2 = open('dump.pkl','rb')
list_loads = pickle.load(f2)
print(list_loads) # 结果: [1,2,3,'d']
json模块
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
json中的方法和pickle中差不多,也是dumps,dump,loads,load。使用上也没有什么区别,区别在于,json中的序列化后格式为字符。
import json
lis_str = json.dumps(list)
print(lis_str)
print(type(lis_str))
lis = json.loads(lis_str)
print(lis)
print(type(lis))
f = open('str.json','w',encoding='utf-8')
json.dump(list,f)
f2 = open('str.json','r',encoding='utf-8')
a = json.load(f2)
print(a)
json和pickle区别:
json:
优点:跨语言、体积小
缺点:只能支持int\str\list\tuple\dict
Pickle:
优点:专为python设计,支持python所有的数据类型
缺点:只能在python中使用,存储数据占空间大
七、logging模块
python的logging模块提供了标准的日志接口,通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical()5个级别。
logging模块的日志可以定义很多种格式,如下表:
序号 | %(name)s | logge名字 |
1 | %(levelno)s | 数字形式的日志级别 |
2 | %(levelname)s | 文本形式的日志级别 |
3 | %(pathname)s | 调用日志输出函数的模块的完整路径名,可能没有 |
4 | %(filename)s | 调用日志输出函数的模块的文件名 |
5 | %(module)s | 调用日志输出函数的模块名 |
6 | %(funcName)s | 调用日志输出函数的函数名 |
7 | %(lineno)d | 调用日志输出函数的语句所在的代码行 |
8 | %(created)f | 当前时间,用UNIX标准的表示时间的浮 点数表示 |
9 | %(relativeCreated)d | 输出日志信息时的,自Logger创建以 来的毫秒数 |
10 | %(asctime)s | 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 |
11 | %(thread)d | 线程ID。可能没有 |
12 | %(threadName)s | 线程名。可能没有 |
13 | %(process)d | 进程ID。可能没有 |
14 | %(message)s | 用户输出的消息 |
Python 使用logging模块记录日志涉及四个主要类:
logger提供了应用程序可以直接使用的接口;每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
他们之间的关系如下:
import logging
from logging import handlers #导入日志截断模块
#创建fillter对象
class IgnoreBackupFilter(logging.Filter):
def filter(self, record):
return 'db backup' not in record.getMessage() #将日志中带db backup的日志忽略掉
#生成 logger 对象
logger = logging.getLogger('web')
#把filtter对象添加到logger中
logger.addFilter(IgnoreBackupFilter())
#设置日志级别
logger.setLevel(logging.DEBUG) # 一般对未输出的日志没有设置级别,则默认此处设置的日志级别;如果输出的日志级别比此处设置全局的日志级别还要低,则按照此处设置的全局日志级别进行输出
#生成 handler 对象
ch = logging.StreamHandler() # 输出日志到屏幕
fh = logging.FileHandler('web.log') # 输出日志到文件中
#截取日志,按照每份日志的大小来保存,超出大小后重新生成新的日志
fh1 = handlers.RotatingFileHandler('web.log',maxBytes=10,backupCount=3) #(日志名称,没份日志大小,保存多少份日志)
#截取日志,按照时间来截取日志
fh2 = handlers.TimedRotatingFileHandler('web.log',when='s',interval= 2,backupCount=3) #(名称,时间级数,时间长度,保存文件个数)
#设置输出日志的级别
ch.setLevel(logging.INFO)
fh.setLevel(logging.WARNING)
#把handler对象绑定到logger
logger.addHandler(ch)
logger.addHandler(fh)
#生成 formatter 对象
# 把formatter 对象绑定handler对象
file_formatter = logging.Formatter('%(asctime)s - %(levelno)s - %(filename)s - %(message)s',
datefmt='%Y-%m-%d %I:%M:%S %p')
console_formatter = logging.Formatter('%(asctime)s - %(levelno)s - %(filename)s - %(message)s - %(lineno)d',
datefmt='%Y-%m-%d %I:%M:%S %p')
ch.setFormatter(console_formatter)
fh.setFormatter(file_formatter)
logger.debug('love you')
logger.info('you love?')
logger.warning('Yes you love')
logger.debug('db backup not love')
日志重复输出优化
import logging
def my_log():
logger = logging.getLogger('mysql.log')
# 每次被调用后打印出logger的handlers列表
print(logger.handlers)
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(fmt)
logger.addHandler(ch)
return logger
my_log().error('run one')
my_log().error('run two')
my_log().error('run three')
#输出结果:
019-02-24 23:59:23,150 - mysql.log - ERROR - run one
2019-02-24 23:59:23,150 - mysql.log - ERROR - run two
2019-02-24 23:59:23,150 - mysql.log - ERROR - run two
2019-02-24 23:59:23,150 - mysql.log - ERROR - run three
2019-02-24 23:59:23,150 - mysql.log - ERROR - run three
2019-02-24 23:59:23,150 - mysql.log - ERROR - run three
[]
[<StreamHandler <stderr> (ERROR)>]
[<StreamHandler <stderr> (ERROR)>, <StreamHandler <stderr> (ERROR)>]
从上面代码运行结果来看,在运行日志输出函数时日志重复了,并且数量成递增趋势,实际上时因为logger = logging.getLogger(‘mysql.log’)在执行时,没有每次生成一个新的logger,而是先检查内存中是否存在一个叫做‘mysql.log’的logger对象,存在则取出,不存在则新建。
1、logger.handlers最初是一个空列表,执行‘logger.addHandler(ch)’添加个‘StreamHandler’,输出一条日志
2、在第二次被调用时,logger.handlers已经存在一个‘StreamHandler’,再次执行‘logger.addHandler(ch)’就会再次添加一 个‘StreamHandler’,此时的logger有两个个‘StreamHandler’,输出两条重复的日志
3、在第三次被调用时,logger.handlers已经存在两个‘StreamHandler’,再次执行‘logger.addHandler(ch)’就会再次添加一个,此时的logger有三个‘StreamHandler’,输出三条重复的日志
解决办法:
# 及时清理(logger.handlers.clear)
def my_log():
logger = logging.getLogger()
# 每次被调用后,清空已经存在handler
logger.handlers.clear()
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(fmt)
logger.addHandler(ch)
return logger
my_log().error('run one')
my_log().error('run two')
my_log().error('run three')
# 用前判断
import logging
def my_log():
logger = logging.getLogger('mysql.log')
# 判断logger是否已经添加过handler,是则直接返回logger对象,否则执行handler设定以及addHandler(ch)
if not logger.handlers:
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(fmt)
logger.addHandler(ch)
return logger
my_log().error('run one')
my_log().error('run two')
my_log().error('run three')
八、re模块
正则表达式就是字符串的匹配规则,一种小型的、高度专业化的编程语言,而在python中,通过内嵌集成re模块。
1、普通字符和11个元字符:
普通字符 | 匹配自身 |
. | 匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符) |
\ | 转义字符,使后一个字符改变原来的意思 |
* | 匹配前一个字符0或多次 |
+ | 匹配前一个字符1次或无限次 |
? | 匹配一个字符0次或1次 |
^ | 匹配字符串开头。在多行模式中匹配每一行的开头 |
$ | 匹配字符串末尾,在多行模式中匹配每一行的末尾 |
| | 或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式 |
{} | {m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次 |
[] | 字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义恢复特殊字符的特殊含义。 |
() | 被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1.分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。 |
这里需要强调一下反斜杠\的作用:
反斜杠后边跟元字符去除特殊功能;(即将特殊字符转义成普通字符)
反斜杠后边跟普通字符实现特殊功能;(即预定义字符)
引用序号对应的字组所匹配的字符串。
2、预定义字符
预定义字符 | 匹配自身 |
\d | 数字:[0-9] |
\D | 非数字:[^\d] |
\s | 匹配任何空白字符:[<空格>\t\r\n\f\v] |
\S | 非空白字符:[^\s] |
\w | 匹配包括下划线在内的任何字字符:[A-Za-z0-9_] |
\W | 匹配非字母字符,即匹配特殊字符 |
\A | 仅匹配字符串开头,同^ |
\Z | 仅匹配字符串结尾,同$ |
\b | 匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | [^\b] |
3、特殊分组
预定义字符 | 匹配自身 |
(?P) | 分组,除了原有的编号外再指定一个额外的别名 |
(?P=name) | 引用别名为的分组匹配到字符串 |
4、re的匹配语法
re.compile()
编译正则表达式模式,返回一个对象的模式。(可以把那些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率。)
格式:re.compile(pattern,flags=0)
pattern: 编译时用的表达式字符串。
import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt)) #查找所有包含'oo'的单词
执行结果如下:
['good', 'cool']
re.match(pattern, string, flags=0)
从起始位置开始根据模型去字符串中匹配指定内容,匹配单个
pattern 正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式
import re
print(re.match('com','comwww.runcomoob').group())
print(re.match('com','Comwww.runcomoob',re.I).group())
执行结果如下:
com
com
flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:
标志 | 含义 |
re.S(DOTALL) | 使.匹配包括换行在内的所有字符 |
re.I(IGNORECASE) | 忽略大小写(括号内是完整写法,下同) |
re.L(LOCALE) | 做本地化识别(locale-aware)匹配,法语等 |
re.M(MULTILINE) | 多行匹配,改变'^'和'$'的行为 |
re.X(VERBOSE) | 可以给你的表达式写注释,使其更可读 |
re.U | 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B |
re.search(pattern, string, flags=0)
re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
import re
print(re.search('\dcom','www.4comrunoob.5com').group())
执行结果如下:
4com
re.findall(pattern, string, flags=0)
match and search均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。
import re
p = re.compile(r'\d+')
print(p.findall('o1n2m3k4'))
执行结果如下:
['1', '2', '3', '4']
re.sub(pattern, repl, string, count=0, flags=0)
用于替换匹配的字符串
import re
c = 'aa12bb33dd55#ffg-df|dX32fd'
print(re.sub('\d+','_',c,count=2))
执行结果如下:
aa_bb_dd55#ffg-df|dX32fd
re.split(pattern, string, maxsplit=0, flags=0)
maxsplit用于指定最大分割次数,不指定将全部分割。
import re
c = 'aa12bb33dd55#ffg-df|dX32fd'
print(re.split('\d+|#|-|\|',c)) #\|将|的语法转换成字符|
执行结果如下:
['aa', 'bb', 'dd', '', 'ffg', 'df', 'dX', 'fd']
re.fullmatch(pattern, string, flags=0)
整个字符串匹配成功就返回re object, 否则返回None
import re
print(re.fullmatch('\[email protected]\w+\.(com|cn|edu)',"[email protected]"))
执行结果:
<re.Match object; span=(0, 17), match='[email protected]'>
注意:
match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
group() 返回被 RE 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置
groups() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。以元组形式返回
groupdict() 将匹配到的结果以字典形式返回,与分组匹配搭配使用
import re
s='41125119910516****'
b = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})',s)
print(b)
print(b.groups())
print(b.groupdict())
执行结果:
<re.Match object; span=(0, 10), match='4112511991'>
('411', '251', '1991')
{'province': '411', 'city': '251', 'born_year': '1991'}
re.match与re.search与re.findall的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
贪婪匹配与非贪婪匹配
?, +? ,??, {m,n}? 前面的,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
import re
a = re.findall(r"a(\d+?)",'a23b')
print(a)
b = re.findall(r"a(\d+)",'a23b')
print(b)
执行结果:
['2']
['23']
使用re模块下的findall()函数的问题
import re
string="abcdefg acbdgef abcdgfe cadbgfe"
#带括号与不带括号的区别
#不带括号
regex=re.compile("((\w+)\s+\w+)")
print(regex.findall(string))
#输出:[('abcdefg acbdgef', 'abcdefg'), ('abcdgfe cadbgfe', 'abcdgfe')]
regex1=re.compile("(\w+)\s+\w+")
print(regex1.findall(string))
#输出:['abcdefg', 'abcdgfe']
regex2=re.compile("\w+\s+\w+")
print(regex2.findall(string))
#输出:['abcdefg acbdgef', 'abcdgfe cadbgfe']
# 第一个 regex 中是带有2个括号的,我们可以看到其输出是一个list 中包含2个 tuple
# 第二个 regex 中带有1个括号,其输出的内容就是括号匹配到的内容,而不是整个表达式所匹配到的结果。
# 第三个 regex 中不带有括号,其输出的内容就是整个表达式所匹配到的内容。
结论:findall()返回的是括号所匹配到的结果(如regex1),多个括号就会返回多个括号分别匹配到的结果(如regex),如果没有括号就返回就返回整条语句所匹配到的结果(如regex2)。所以在提取数据的时候就需要注意。