八、库
(一)基础知识
1.pip工具安装
# pip工具安装
pip install <包名> 安装
pip uninstall <> 卸载
pip list 查询所有库
pip show <> 详细查询
pip download <> 下载
pip search <> 查询关键字
2.模块变量
(1)python程序结构
文件夹(项目根目录)-- 包 - 模块 - 类 - 函数 - 语句
包:将模块以文件夹的形式进行分组管理
3.模块
包含一系列数据、函数、类的文件,以.py结尾
作用:使结构清晰
调用模块(系统或第三方)
import <>
from <模块> import <具体模块> or *
import <模块名> as <别名>
#自定义模块在调用时,建议将项目主文件路径加入path中
#在启动文件中加入下列代码
3.5以下的版本
import sys #好处:项目内的可以跨文件夹调用
__file__ #显示当前文件的绝对路径
os.path.dirname(__file__) #__file__ 的父亲文件的路径
re=os.path.dirname(os.path.dirname(__file__)) #项目主文夹
sys.path.append(re)
3.5以后的版本
from pathlib import Path
Path(__file__).parent.parent #项目主文夹
res =Path('/a/a') / "d/e.txt" #拼接
res.resolve() #规范路径
4.包 定义 将模块以文件夹的形式进行分组管理 作用 使结构清晰 调用
from <包.模块> import <成员> from <包.包.模块> import <成员> import.<包>.<模块>
(二)系统操作库
1.os库
方法 | 说明 |
---|---|
os.getcwd() | 获取当前工作目录,即当前python脚本工作的目录路径 |
os.chdir ( "dirname") | 改变当前脚本工作目录;相当于shell下cd |
os.curdir | 返回当前目录:"-") |
os.pardir | 获取当前目录的父目录字符串名: (..-") |
os.makedirs ( 'dirname1/dirname2 ") | 可生成多层递归目录 |
os.removedirs ( 'dirname1') | 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 |
os.mkdir ( 'dirname " ) | 生成单级目录;相当于shel1中mkdir dirname |
os . rmdir ( 'dirname " ) | 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname |
os.listdir ( "dirname ' ) | 列出指定目录下的所有文件和子目录,包括隐藏文件。并以列表方式打印 |
os. remove() | 删除一个文件 |
os.rename ( "oldname", "newname") | 重命名文件/目录 |
os.stat( 'path/filename") | 获取文件/目录信息 |
os.sep | 输出操作系统特定的路径分隔符,win下为"\1",Linux下为"/" |
os. linesep | 输出当前平台使用的行终止符,win下为"\r",Linux下为"\n” |
os.pathsep | 输出用于分割文件路径的字符串win下为; , Linux下为: |
os.name | 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' |
os.system ( "bash command") | 运行shell命令,直接显示 |
os.environ | 获取系统环境变量 |
os.path . abspath (path) | 返回path规范化的绝对路径 __ file __ 当前文件路径 |
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 path.isdir (r" “) |
os.path.join(path1[,path2[,..….]]) | 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 |
os.path.getatime (path) | 返回path所指向的文件或者目录的最后存取时间 |
os.path.getmtime (path) | 返回path所指向的文件或者目录的最后修改时间 |
os.path.getsize (path) | 返回path的大小 |
2.sys库
方法 | 说明 |
---|---|
sys.argv | 命令行参数List,获取解释器后的参数,第一个元素是程序本身路径 |
sys.exit (n) | 退出程序,正常退出时exit (0) |
sys.version | 获取Python解释程序的版本信息 |
sys.maxint | 最大的Int值 |
sys.path | 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 |
sys.platform | 返回操作系统平台名称 |
#通用的复制器----使用b模式
import sys
src1 = sys.argv[1] #复制的文件
src2 = sys.argv[2] #目标
def copy(url,url2):
"""
url :被复制的文件的路径
url2:新文件
"""
with open(url,"rb") as f1,open(url2,"wb") as f2:
for item in f1: #读出每行
f2.write(item) #写进每行
shell 命令
python3 <文件名> copy <文件名> <新文件>
#打印进度条
import time
import random
recv_size = 0 #已下载的数据大小 Byte
total_size = 456894 #下载总量 Byte
def progress(recv_size,total_size):
time.sleep(1)
speed = random.randint(1024,2048)
if total_size-recv_size>speed:
recv_size += speed
print_schedule(recv_size,total_size)
else:
recv_size += total_size-recv_size
print_schedule(recv_size,total_size)
def print_schedule(recv_size,total_size): #打印进度条
temp = recv_size/total_size
print("\r{: <50}{}".format(int(temp*50)*"*",int(temp*100)), end="") #
(三)时间库
1.time库
方法 | 说明 |
---|---|
.time() | 获取当前时间戳(从1970年1月1日到现在的秒)可以算数运算 |
.localtime( [<时间戳>] ) | 时间元组,为空则获取当前时间 |
.mktime(<时间元组>) | 将时间元组=>时间戳 |
.strftime(<%Y-%m-%d %H:%M:%S>[,<时间元组>]) | 时间元组=>字符串,可以省略 |
.strptime("时间字符串",format) | 字符串 =>时间元组 |
.sleep(s) | 程序停顿s秒 |
.asctime() | 作用与strftime相同 |
%a Locale's abbreviated weekday name.
%A Locale's full weekday name .
%b Locale's abbreviated month name.
%B Locale's full month name .
%c Locale's appropriate date and time representation.
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock)as a decimal number [00,23].
%I Hour (12-hour clock) as a decimal number [01,12].
%j Day of the year as a decimal number [001,366].
%m Month as a decimal number [01,12].
%M Minute as a decimal number [00,59].
%p Locale's equivalent of either AM or PM.(1)
%S Second as a decimal number [0o,61].(2)
%U week number of the year (Sunday as the first day of the week) as a decimal number[00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.(3)
%w weekday as a decimal number [0(Sunday) ,6].
%W Week number of the year (Monday as the first day of the week) as a decimal number[00,53]. All days in a new year preceding the first Monday are considered to be in week 0.(3)
%x Locale's appropriate date representation.
%X Locale's appropriate time representation.
%y rear without century as a decimal number [o0,99].
%Y rear with century as a decimal number.
%z Time zone offset indicating a positive or negative time difference from vrc/GMT of theform +HHN or -HHNM,where H represents decimal hour digits and M represents decimal minutedigits [-23:59,+23:59].
%Z Time zone name (no characters if no time zone exists).
2.datetime模块
方法 | 说明 |
---|---|
.datetime.now() | 获取当前日期时间,可以算数运算,需要借用.timedalta( ) |
.timedalta(year,month,day[,....] ) | |
import datetime
print(datatime.datetime.now()+datetime.timedalta(day=-3))
(四)jieba库
方法 | 说明 |
---|---|
.lcut(s) | 精确模糊 |
.lcut(s,cut_all = True) | 全模式 |
add_word(w) | 向分词字典增加新词w |
(五)数学库
1.random库
方法 | 说明 |
---|---|
seed() | |
random() | 产生【0,1)之间的小数、 |
randint(a,b) | 产生【a,b]之间的整数 |
getrandbits(k) | |
uniform(a,b) | (a,b)之间的小数 |
choice(seq) | 随机返回seq容器里的内容 |
randrange(start,stop[,step]) | 产生【start,stop)之间的整数 |
shuffle(seq) | 打乱seq容器的顺序 |
sample(pop,k) | 随机返回pop容器里的k个内容 |
#验证码
import random
def get_verification_code(n):
lists= []
for i in range(n):
randint = random.randint(0,10):
if randint in (list(range(0,4))):
lists.append(str(random.randint(0,9)))
elif randint in (list(range(4,7))):
lists.append(chr(andom.randint(65,90)))
elif randint in (list(range(7,10))):
lists.append(chr(andom.randint(97,122)))
return "".join(lists)
(六)绘图库
1.turtle库
类型 | 方法 | 说明 |
---|---|---|
窗体函数 | .setup(width,height,startx,starty) | |
画笔函数 | penup() | 提起画笔 |
pendown() | 放下画笔 | |
pensize(width) | 画笔线条粗细 | |
pencolor() | 画笔的颜色 | |
.fillcolor() | 填充颜色 | |
color() | 设置画笔颜色和填充颜色 | |
begin_fill() | 填充颜色开始的函数 | |
end_fill() | 填充颜色结束的函数 | |
画笔运动 | forward(distance) | 画笔向前运动 |
backward() | 画笔向后运动 | |
right(angle) | 向右旋转angle角度 | |
left(angle) | 向左旋转angle角度 | |
goto(x,y) | 移动到绝对坐标(x,y)处 | |
seth(to_angle) | 旋转多少度 | |
circle(radiua,e/steps) | 绘制一个半径为r,角度e的圆或弧形,或steps=3正3边行 |
(七)文件库
后期加入
(八)shutil模块
高级的文件、文件夹、压缩包处理模块
shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中
import shutil
shutil.copyfileobj(open ( 'old.xml ' , 'r'),open ( 'new.xml ', 'w '))
shutil.copyfile(src, dst) 拷贝文件
shutil.copyfile( 'f1.log', 'f2.log ')#目标文件无需存在
shutil.copymode(src, dst) 仅拷贝权限。内容、组、用户均不变
shutil.copymode ( 'f1.log', 'f2.log')#目标文件必须存在
shutil.copystat(src, dst) 仅拷贝状态的信息,包括: mode bits, atime, mtime, flags
shutil.copystat ( 'f1.log', '2.log ')#目标文件必须存在
shutil.copy[sre, dst)接贝文件和权限
import shutil
shutil.copy (' t1.ltg' . 'r2.lag ' )
shutil.copy2(src, dst) 拷贝文件和状态信息
shatil.copy2( 'f1.lag', 'E2.loT")
shutil.ignore_patterns(patterns) shutil.copytree(src, dst, symlinks=False, ignore=None)递归的去拷贝文件夹
import shutil
shutil.copytree('folder1','folder2 ' , ignore=shutil.ignore_patterns ( '*.pyc ','tmp* '))#目标目录不能存在,注意对folder2目录父级目录要有可写权限, ignore的意思是排除
田拷贝软连接
shutil.rmtree(path[, ignore_errors[, onerror]]) 递归的去删除文件
limport shutil2 shutil.rmtree ( 'folder1')
shutil.move(src, dst) 递归的去移动文件,它类似mv命令,其实就是重命名。
import shutil shutil.move ( 'folder1', 'folder3 ' )
shutil.make_archive(base_name, format,...)创建压缩包并返回文件路径,例如:zip、tar创建压缩包并返回文件路径,例如:zip、tar . base_name:压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至 指定路径, 如data_bak =>保存至当前路径 如:/tmp/data_bak =>保存至/tmpl . format:压缩包种类,“zip","“tar", "bztar",“gztar". root_dir:要压缩的文件夹路径(默认当前目录). owner:用户,默认当前用户 . group:组,默认当前组 . logger:用于记录日志,通常是logging.Logger对象
#将/ data下的文件打包放置当前程序目录import shutil
ret = shutil.make_archive ("data_bak", 'gztar', root_dir='/data ')
#将/data下的文件打包放置/ tmp/目录
import shutil
ret = shutil.make_archive (" /tmp/data_bak",'gztar', root_dir='/data ')
(九)json模块&pickle模块
1.序列化
序列化指的是把内存的数据类型转换成一个特定的格式的内容
内存中的数据类型-—-->序列化---—>特定的格式(json格式或者pickle格式)
内存中的数据类型<---反序列化<--—-特定的格式(json格式或者pickle格式) (反序列化)
作用:
该格式的内容可用于存储(存档) pickle 只有python独有
传输给其他平台使用(跨平台) json 被所有语言识别
2.json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | str |
1234.56 | int float |
true false | True False |
null | None |
方法
方法 | 说明 |
---|---|
dumps( <>) | 转化为序列(字符串) |
.loads(<序列>) | 序列 ->代码(与eval相似) |
dump( <内容>,<文件变量>) | 将序列化的内容保存到文件内 |
import json
res = json.dumps(True) #"true"
res = json.dumps([1,2]) #"[1,2]"
with open("text.txt","wt") as p:
p.write(res)
with open ("text.json","wt") as f:
josn.dump(res,["5",4])
注:ujson模块与json的作用和用法相同,但比json 效率高
3.pickle模块
方法
方法 | 说明 |
---|---|
dumps( <>) | 转化为序列(字符串) |
.loads(<序列>) | 序列 ->代码(与eval相似) |
dump( <内容>,<文件变量>) | 将序列化的内容保存到文件内 |
import pickle
res = pickle.dumps(True) #"true"
res = pickle.dumps([1,2]) #"[1,2]"
with open("text.txt","wt") as p:
p.write(res)
with open ("text.json","wt") as f:
pickle.dump(res,["5",4])
(十)configparser模式
#配置文件
#语法
#定义
import configparser
[section1]
k1 = v1
k2 : v2
user=egonage=18
is_admin=truesalary=31
[section2]
k1 = v1
#调用
import configparser
#将配置文件加载到内存
config =configparser.ConfigParser()
config.read("test.ini")
#获取配置内容
condig.setions() #["section1","section2"]
#获取某一section下的所有options
config.options("section1") #["k1","k2","user","is_admin"]
#获取items
config.items("sections1") #[( 'k1',‘v1'),(' k2','v2'),...]
config.get("sections1","user") #"18" str
config.getint("sections1","user") #18 int
config.getboolean("sections1","user") #True
config.getfloat("sections1","user") #18.0
(十一)hashlib模块
1.概念
2.语法
import hashlib
hash = hashlib.md5() #哈希生成器
hash.update("hello".encode("utf-8")) #输入需要转化的字符
hash.hexdigest() #输出结果
3.密码加盐--增加复杂度
#模拟撞库
hashpaa = " "
password_list = [
"123",
"1234"
] #撞库的密码
import hashlib
for item in password_list:
hash = hashlib.md5()
hash.update(item.encode("utf-8"))
if hash.hexdigest() == hashpaa:
print(item,"找到了")
else:
print("没找到")
#密码加盐--实质是在密码中增加额外部分,增加复杂度,增加撞库的成本
import hashlib
hash.update("墨非墨".encode("utf-8"))
hash.update("密码部分".encode("utf-8"))
hash.hexdigest()
(十二)subprocess模块
import subprocess
#执行“ ”里shell命令 查看文件夹的内容
obj=subprocess.Popen("ls /root",shell=True,
stdout=subprocess.PIPE,#将正确的结果传到 stdout
stdeff=subprocess.PIPE)#将错误的结果传到 stdeff
obj.stdout.read() #查看结正确结果
obj.stdeff.read().decode("utf-8")#查看结错误结果,以utf8编码格式
(十二)日志模块
#settings.py
import os
import logging
#一:日志配置
logging.basicconfig(
"""
#1、日志输出位置: 1、终端 2、文件
#filename='access.log',#不指定,默认打印到终端
#2、日志格式
#format='%(asctime)s - %(name)s - %(levelname)s -&(module)s: %(message)s', #时间 名字 等级 哪一行
1、定义三种日志输出格式,日志中可能用到的格式化串如下
%(name)s Logger的名字
%(evelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIx标准的表示时间的浮点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是“2003-07-08 16:49:45,896""。逗号后面的是毫秒
%(thread)d线程ID。可能没有
%(threadName)s 线程名。可能没有
# (process)d进程工D。可能没有
%(message)s用户输出的消息
2、强调:其中的%(name)s为getlogger时指定的名字
#3、时间格式 自定义
datefmt='%Y-%m-%d%H:%M:%S %p',
#4、日志级别
# critical ->50
# error =>40
# warning =>30
# info ->20
# debug -=>10
level=10,
""")
#1.输出日志的模板
standard_format = '%(asctime)s - %(threadName)s:%(thread)d - 日志名:%(name)s - %(filename) s:%(lineno)d - \
%(levelname) s - %(message) s'
simple_format= '[%(levelname)s][%(asctime)s][%(filename)s:% (lineno)d]%(message)s'
test_format = '[%(asctime)s]%(message)s'
#2.配置字典
LOGGING_DIC = {
"version ' : 1,
'disable_existing_loggers ': False,
#展示日志格式
'formatters ': {
'standard ' : {
'format ' : standard_format #调用日志模板
},
'simple' : {
'format ' : simple_format
},
"test': {
'format': test_format
},
},
'filters ' : {},
#控制日志输出位置
' handlers' : {
#打印到终端的日志
"console': {
'level': 'DEBUG ' , #日志级别
'class ' : 'logging.StreamHandler',#打印到屏幕
'formatter' : 'simple' #展示日志格式},
#打印到文件的日志收集infQ及以上的日志
"default':{'level': 'DEBUG ', #日志级别
'class ' : 'logging. handlers.RotatingFileHandler' ,#保存到文件,并开启轮转功能
'formatter' : 'standard ' ,
#可以定制日志文件路径
#BASE_DIR = os.path.dirname( os.path.abspath(__file__)
#LOG_PATH = os.path.join( BASE_ DIR, 'a1.log ')
'filename ' : 'a1.log ' ,#日志文件
' maxBytes ' : 1024*1024*5,#日志大小5M
' backupCount ' : 5, #最多轮转5次
'encoding': 'utf-8',#日志文件的编码 },
'other ' : {
"level': "DEBUG' ,
'class ' : 'logging.FileHandler',#保存到文件
'formatter' : 'test',
'filename ' : 'a2.log ',
#os.path.join(os.path.dirname(os.path.dirname(__file__)),'a2.log ')项目文件
' encoding ': 'utf-8 " ,
},
},
#产生不同级别日志,日志产生者
'loggers' : {
#loaging.getLogger(__name__)拿的logger配置
"<日志名> ": {
'handlers ': [ ' default ', ' console'],#"<变量>"产生的日志丢给[]
'level': ‘DEBUG " , # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关限制) 可以输出aaa.debug("")级别高的 .info()
'propagate ': False,#默认为True,向上(更高level的logger)传递,通常设False
},
" a":{
' hand lers ' : [ 'other'],
' level' : 'DEBUG ' ,
' propagate' : False,},
},
" b":{
' hand lers ' : [ 'default'],
' level' : 'DEBUG ' ,
' propagate' : False,},
},
},
}
#二:输出日志
logging.debug( '调试debug ' ) #往下,等级越高
logging.info('消息info')
logging.warning( "警告warn ")
logging.error( "错误error")
logging.critical ( '严重critical ')
"""
·注意下面的root是默认的日志名字
WARNING : root:警告warn
ERROR : root:错误error
CRITICAL: root:严重critical
"""
#使用日志的文件
import settings
from logging import config,getLogger
#导入日志配置
#1.导入配置字典
config.dictConfig(settings.LOAGGING_DIC)
#拿到日志的产生者
loagger1=getLogger("a")
loagger1.infor("") #产生日志
loagger2=getLogger("b")
loagger2.infor("") #产生日志
日志名:是用于区分日志业务
日志轮转 #为了防止日志文件太大,所进行的分割
日志记录者程序员运行过程中的关键信息
(十三)正则表达式(re)
1.简介
定义
原理
2.元字符
(1)普通字符
-
匹配规则:每个普通字符匹配其对应的字符
email = "墨非墨: 1433830053@qq.com"
import re
re.findall("\w+@\w+\.cn") #1433830053@qq.com
-
注意事项:正则表达式在python中也可以匹配中文
(2)或关系
-
元字符: |
-
匹配规则: 匹配 | 两侧任意的正则表达式即可
e.g.
In : re.findall('com|cn',"www.baidu.com/www.tmooc.cn")
Out: ['com', 'cn']
(3)匹配单个字符
-
元字符: .
-
匹配规则:匹配除换行外的任意一个字符
import re
re.findall("贾.春","贾元春,贾迎春,贾探春,贾惜春")
#["贾元春",贾迎春",贾探春","贾惜春"]
(4)匹配字符集
-
元字符: [字符集]
-
匹配规则: 匹配字符集中的任意一个字符
-
表达形式:
import re
re.findall(["元迎探惜"],"贾元春,贾迎春,贾探春,贾惜春")
#["元","迎","探","惜"]
re.findall([0-9],"今年2022年")
#["2","0","2","2"]
(5)匹配字符集反集
-
元字符:[ ^ 字符集]
-
匹配规则:匹配除了字符集以外的任意一个字符
e.g.
In : re.findall('[^0-9]',"Use 007 port")
Out: ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']
(6)匹配字符串开始位置
-
元字符: ^
-
匹配规则:匹配目标字符串的开头位置
import re
re,findall("^林黛玉|^薛宝钗","贾元春,贾迎春,贾探春,贾惜春,林黛玉,薛宝钗")
#["林黛玉","薛宝钗"]
re.findall('[^ ]+',"Port-9 Error #404# %@STD")
['Port-9', 'Error', '#404#', '%@STD']
(7)匹配字符串的结束位置
-
元字符: $
-
匹配规则: 匹配目标字符串的结尾位置
e.g.
In : re.findall('Jame$',"Hi,Jame")
Out: ['Jame']
-
规则技巧: ^ 和 $必然出现在正则表达式的开头和结尾处。如果两者同时出现,则中间的部分必须匹配整个目标字符串的全部内容。
(8)匹配字符重复
-
元字符: *
-
匹配规则:匹配前面的字符出现0次或多次
e.g.
In : re.findall('wo*',"wooooo~~w!")
Out: ['wooooo', 'w']
import re
re.findall("[0-9]*","MFM13")
#["13"]
re.findall('[A-Z][a-z]*',"Hello World") #匹配一个大写字母+多个小写
-
元字符:+
-
匹配规则: 匹配前面的字符出现1次或多次
e.g.
In : re.findall('[A-Z][a-z]+',"Hello World")#匹配一个大写字母+至少1个小写
Out: ['Hello', 'World']
-
元字符:?
-
匹配规则: 匹配前面的字符出现0次或1次
import re
re,findall(".春?","贾元春,贾迎春,贾探春,贾惜春,林黛玉,薛宝钗")
>>> re.findall('-[0-9]*|[0-9]*',"167,-28,29,-8")
['167', '', '-28', '', '29', '', '-8', '']
>>> re.findall('-?[0-9]*',"167,-28,29,-8")
['167', '-28', '29', '-8',]
-
元字符:{n}
-
匹配规则: 匹配前面的字符出现n次
e.g. 匹配手机号码
In : re.findall('1[0-9]{10}',"Jame:13886495728")
Out: ['13886495728']
re.findall('张.{2}',"张飞 张翼德")
['张飞 ', '张翼德']
-
元字符:{m,n}
-
匹配规则: 匹配前面的字符出现m-n次
e.g. 匹配qq号
In : re.findall('[1-9][0-9]{5,10}',"Baron:1259296994")
Out: ['1259296994']
(9)匹配任意(非)数字字符
-
元字符: \d \D
-
匹配规则:\d 匹配任意数字字符,\D 匹配任意非数字字符
e.g. 匹配端口
In : re.findall('\d{1,5}',"Mysql: 3306, http:80")
Out: ['3306', '80']
(10)匹配任意(非)普通字符
-
元字符: \w \W
-
匹配规则: \w 匹配普通字符,\W 匹配非普通字符
-
说明: 普通字符指数字,字母,下划线,汉字。
e.g.
In : re.findall('\w+',"server_port = 8888")
Out: ['server_port', '8888']
(11)匹配任意(非)空字符
-
元字符: \s \S
-
匹配规则: \s 匹配空字符,\S 匹配非空字符
-
说明:空字符指 空格 \r \n \t \v \f 字符
e.g.
In : re.findall('\w+\s+\w+',"hello world")
Out: ['hello world']
(12)匹配开头结尾位置
-
元字符: \A \Z
-
匹配规则: \A 表示开头位置,\Z 表示结尾位置
(13)匹配(非)单词的边界位置
-
元字符: \b \B
-
匹配规则: \b 表示单词边界,\B 表示非单词边界
-
说明:单词边界指数字字母(汉字)下划线与其他字符的交界位置。
e.g. In : re.findall(r'\bis\b',"This is a test.") Out: ['is']
类别 | 元字符 |
---|---|
匹配字符 | . [...] [ ^ ...] \d \D \w \W \s \S |
匹配重复 | * + ? {n} {m,n} |
匹配位置 | ^ $ \A \Z \b \B |
其他 | | () \ |
3.正则表达式的转义
-
如果使用正则表达式匹配特殊字符则需要加 \ 表示转义。
e.g. 匹配特殊字符 . 时使用 \. 表示本身含义
In : re.findall('-?\d+\.?\d*',"123,-123,1.23,-1.23")
Out: ['123', '-123', '1.23', '-1.23']
-
在编程语言中,常使用原生字符串书写正则表达式避免多重转义的麻烦。
e.g.
python字符串 --> 正则 --> 目标字符串
"\\$\\d+" 解析为 \$\d+ 匹配 "$100"
"\\$\\d+" 等同于 r"\$\d+"
>>> re.findall('-?[0-9]*\.?[0-9]?',"167,-28,29,-8,-3.8")
['-28', '-8', '-3.8']
>>> re.findall('-?\d+\.?\d+',"167,-28,29,-8,-3.8")
['-28', '-8', '-3.8']
re.findall(r'-?\d+\.?\d+',"167,-28,29,-8,-3.8") #标准格式
['-28', '-8', '-3.8']
4.贪婪模式和非贪婪模式
-
定义
-
贪婪模式转换为非贪婪模式
-
在匹配重复元字符后加 '?' 号即可
* : *?
+ : +?
? : ??
{m,n} : {m,n}?
e.g.
In : re.findall(r'\(.+\)',"(abcd)efgh(higk)") #贪婪模式
Out: "(abcd)efgh(higk)"
In : re.findall(r'\(.+?\)',"(abcd)efgh(higk)")
Out: ['(abcd)', '(higk)']
s = "[林黛玉],[贾府],[萍儿]"
re.findall(r'\[\w+?\]',s)
1.匹配一个.com邮箱格式字符串
str = "1433830053@qq.com"
re.findall(r'\w+@\w+.com$',str)
#['1433830053@qq.com']
2.匹配一个密码8-12位数字字母下划线构成
re.findall(r'\w{8,12}',pass)
3.匹配一个数字正数,负数﹐整数,小数﹐分数1/2﹐百分数45%
strs = "45 -45 4.5 20.45 1/2 45%"
re.findall(r'-?\d+\.?/?\d%?+',strs)
#['45', '-45', '4.5', '20.45','1/2', '45%']
4.匹配一段文字中以大写字母开头的单词﹐注意文字中可能有iPython(不算)H-base(算)
单词可能有大写字母小写字母-」x
strs = "Hello H-base iPython"
re.findall(r'^[A-Z][-_a-zA-Z]*',strs)
5.正则表达式分组
-
定义
-
作用
-
可以被作为整体操作,改变元字符的操作对象
e.g. 改变 +号 重复的对象 In : re.search(r'(ab)+',"ababababab").group() Out: 'ababababab' e.g. 改变 |号 操作对象 In : re.search(r'(王|李)\w{1,3}',"王者荣耀").group() Out: '王者荣耀'
-
可以通过编程语言某些接口获取匹配内容中,子组对应的内容部分
e.g. 获取url协议类型 re.search(r'(https|http|ftp|file)://\S+',"https://www.baidu.com").group(1) #https
-
捕获组
可以给正则表达式的子组起一个名字,表达该子组的意义。这种有名称的子组即为捕获组。
e.g. 给子组命名为 "pig" In : re.search(r'(?P<pig>ab)+',"ababababab").group('pig') Out: 'ab'
-
注意事项
-
一个正则表达式中可以包含多个子组
-
子组可以嵌套,但是不要重叠或者嵌套结构复杂
-
子组序列号一般从外到内,从左到右计数
6.正则表达式匹配原则
-
正确性,能够正确的匹配出目标字符串.
-
排他性,除了目标字符串之外尽可能少的匹配其他内容.
-
全面性,尽可能考虑到目标字符串的所有情况,不遗漏.
7.Python re模块使用
regex = compile(pattern,flags = 0) 功能: 生产正则表达式对象 参数: pattern 正则表达式 flags 功能标志位,扩展正则表达式的匹配 返回值: 正则表达式对象
re.findall(pattern,string,flags = 0) 功能: 根据正则表达式匹配目标字符串内容 参数: pattern 正则表达式 string 目标字符串 flags 功能标志位,扩展正则表达式的匹配 返回值: 匹配到的内容列表,如果正则表达式有子组则只能获取到子组对应的内容
regex.findall(string,pos,endpos) 功能: 根据正则表达式匹配目标字符串内容 参数: string 目标字符串 pos 截取目标字符串的开始匹配位置 endpos 截取目标字符串的结束匹配位置 返回值: 匹配到的内容列表,如果正则表达式有子组则只能获取到子组对应的内容
re.split(pattern,string,flags = 0) 功能: 使用正则表达式匹配内容,切割目标字符串 参数: pattern 正则表达式 string 目标字符串 flags 功能标志位,扩展正则表达式的匹配 返回值: 切割后的内容列表
re.sub(pattern,replace,string,max,flags = 0) 功能: 使用一个字符串替换正则表达式匹配到的内容 参数: pattern 正则表达式 replace 替换的字符串 string 目标字符串 max 最多替换几处,默认替换全部 flags 功能标志位,扩展正则表达式的匹配 返回值: 替换后的字符串
re.subn(pattern,replace,string,max,flags = 0) 功能: 使用一个字符串替换正则表达式匹配到的内容 参数: pattern 正则表达式 replace 替换的字符串 string 目标字符串 max 最多替换几处,默认替换全部 flags 功能标志位,扩展正则表达式的匹配 返回值: 替换后的字符串和替换了几处
import re # 目标字符串 s = "Alex:1994,Sunny:1999" pattern = r"(\w+):(\d+)" # 正则表达式 # re调用函数 l = re.findall(pattern,s) print(l) # regex表达式对象调用函数 regex = re.compile(pattern) l = regex.findall(s,) # 截取s[0:13]作为匹配目标 print(l) # 按照正则匹配的内容,分割目标 l = re.split(r'[,:]',s) print(l) # 使用字符串替换匹配到的部分 s = re.subn(r':','-',s,1) print(s)
re.finditer(pattern,string,flags = 0) 功能: 根据正则表达式匹配目标字符串内容 参数: pattern 正则表达式 string 目标字符串 flags 功能标志位,扩展正则表达式的匹配 返回值: 匹配结果的迭代器
re.fullmatch(pattern,string,flags=0) 功能:完全匹配某个目标字符串 参数:pattern 正则 string 目标字符串 返回值:匹配内容match object
re.match(pattern,string,flags=0) 功能:匹配某个目标字符串开始位置 参数:pattern 正则 string 目标字符串 返回值:匹配内容match object
re.search(pattern,string,flags=0) 功能:匹配目标字符串第一个符合内容 参数:pattern 正则 string 目标字符串 返回值:匹配内容match object
compile对象属性
【1】 pattern : 正则表达式 【2】 groups : 子组数量 【3】 groupindex : 捕获组名与组序号的字典
""" regex1.py re模块 功能函数演示2 生成 match 对象 """ import re s = "今年是2019年,建国70周年" pattern = r"\d+" # 返回迭代对象 it = re.finditer(pattern,s) for i in it: print(i.group()) # 获取match对象对应内容 # 完全匹配 obj = re.fullmatch(r'.+',s) print(obj.group()) # 匹配开始位置 obj = re.match(r'\w+',s) print(obj.group()) # 匹配第一处 obj = re.search(r'\d+',s) print(obj.group())
8.match对象的属性方法
参考代码day13/regex2.py
-
属性变量
-
pos 匹配的目标字符串开始位置
-
endpos 匹配的目标字符串结束位置
-
re 正则表达式
-
string 目标字符串
-
lastgroup 最后一组的名称
-
lastindex 最后一组的序号
-
属性方法
-
span() 获取匹配内容的起止位置
-
start() 获取匹配内容的开始位置
-
end() 获取匹配内容的结束位置
-
groupdict() 获取捕获组字典,组名为键,对应内容为值
-
groups() 获取子组对应内容
-
group(n = 0)
功能:获取match对象匹配内容 参数:默认为0表示获取整个match对象内容,如果是序列号或者组名则表示获取对应子组内容 返回值:匹配字符串
"""
regex2.py
match对象属性实例
"""
import re
pattern = r"(ab)cd(?P<pig>ef)"
regex = re.compile(pattern)
obj = regex.search("abcdefghi",0,7) # match对象
# 属性变量
print(obj.pos) # 目标字符串开始位置
print(obj.endpos) # 目标字符串结束位置
print(obj.re) # 正则
print(obj.string) # 目标字符串
print(obj.lastgroup) # 最后一组组名
print(obj.lastindex) # 最后一组序号
print("=====================================")
# 属性方法
print(obj.span()) # 匹配到的内容在目标字符串中的位置
print(obj.start())
print(obj.end())
print(obj.groups()) # 子组内容对应的元组
print(obj.groupdict()) # 捕获组字典
print(obj.group()) # 获取match对象内容
print(obj.group('pig'))
9.flags参数扩展
-
使用函数:re模块调用的匹配函数。如:re.compile,re.findall,re.search....
-
作用:扩展丰富正则表达式的匹配功能
-
常用flag
-
使用多个flag
方法:使用按位或连接 e.g. : flags = re.I | re.A
"""
flags.py 扩展功能标志
"""
import re
s = """Hello
北京"""
# 只能匹配ascii码
# regex = re.compile(r'\w+',flags=re.A)
# 忽略字母大小写
# regex = re.compile(r'[a-z]+',flags=re.I)
# 让 . 可以匹配\n
# regex = re.compile(r'.+',flags = re.S)
# ^ $ 可以匹配每行的开始结束位置
regex = re.compile(r'Hello$',flags=re.M)
l = regex.findall(s)
print(l)