常用语法:
字符
. | 匹配任意除换行符“\n”外的字符 |
---|---|
\ | 转义字符,使用后一个字符改变原来的意思 |
[..] | 字符集 |
预定义字符集:
\d | 数字:[0-9] |
---|---|
\D | 非数字:[^\d】 |
\s | 空白字符:[<空格>\t\r\n\f\v] |
\S | 非空白字符:[^\s】 |
\w | 单词字符:[A-Za-z0-9] |
\W | 非空白字符:[^w |
数词量:
* | 匹配前一个字符0词或无限次 |
---|---|
+ | 匹配前一个字符1次或者无限次 |
? | 匹配前一个字符0次或1次 |
匹配前一个字符m次 | |
匹配前一个字符m至n次 | |
边界匹配(不消耗待匹配字符串中的字符)
^ | 匹配字符串开头 |
---|---|
$ | 匹配字符串结尾 |
\A | 仅匹配字符串开头 |
\Z | 仅匹配字符串结尾 |
\b | 匹配\w和\W之间 |
\B | [^B] |
逻辑,分组
\ | 代表表达式任意匹配一个 |
---|---|
(..) | 被括起来的表达式将作为分组 |
[^..…] | 匹配除了这组字符以外的字符 |
正则表达式相关注解
(1)数量词的贪婪模式与非贪婪模式
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式”ab”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab?”,将找到”a”。
注:我们一般使用非贪婪模式来提取。
(2)反斜杠问题
转义,在符号前面加上/
与大多数编程语言相同,正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”\”,那么使用编程语言表示的正则表达式里将需要4个反斜杠”\\”:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\”表示。同样,匹配一个数字的”\d”可以写成r”\d”。有了原生字符串,妈妈也不用担心是不是漏写了反斜杠,写出来的表达式也更直观勒。
re模块
findall:
匹配所有内容,形成一个列表,每一项都是列表中的一个元素
s = 'https://ygdy8.com/html/gndy/dyzz/20191022/59284.html">2019年悬疑恐怖《暗战》BD韩<|'
#`findall`匹配所有内容,形成一个列表,每一项都是列表中的一个元素
res = re.findall('com(.*?)5928',s)
print(res)
#['/html/gndy/dyzz/20191022/']
search:只匹配符合条件的从左到右的第一个,得到的不是直接结果,而是一个变量,通过此变量的group方法来获得最后结果,如果没有匹配到符合条件的,则会返回None,使用group会报错
res = re.search('com(.*?)5928',s)
print(res.group())
#com/html/gndy/dyzz/20191022/5928
match:从头开始匹配,相当于search中的正则表达式加上一个"^"
res = re.match('[a-z]{3}',s)
print(res.group())
#htt
字符串处理的扩展
split:切割****,返回列表****
res = re.split('\d+',s)
print(res)
#['https://ygdy', '.com/html/gndy/dyzz/', '/', '.html">', '年悬疑恐怖《暗战》BD韩<|']
sub:切换(旧,新,对象,替换次数)
res = re.sub('\d','*',s)
print(res)
#https://ygdy*.com/html/gndy/dyzz/********/*****.html">****年悬疑恐怖《暗战》BD韩<|
subn:也是替换,不过会返回一个元组,元组中第一个元素是替换后的结果,第二个参数是替换的次数
res = re.subn('\d','*',s)
print(res)
#('https://ygdy*.com/html/gndy/dyzz/********/*****.html">****年悬疑恐怖《暗战》BD韩<|', 18)
re模块的进阶
compile:节省使用正则表达式解决问题的时间,将正则表达式编译成字节码,多次使用过程中不会再多次编译,直接拿来用
s = 'https://ygdy8.com/html/gndy/dyzz/20191022/59284.html">2019年悬疑恐怖《暗战》BD韩<|'
ret = re.compile('\d+') #已经完成编译了
res = ret.findall(s) #拿来直接用
print(res)
#['8', '20191022', '59284', '2019']
finditer
:节省使用正则表达式解决问题的空间,也就是内存
返回一个迭代器,所有的结果都在这个迭代器中,需要通过循环+group的形式取值 能够节省内存
ret = re.finditer('\d+',s)
for i in ret:
print(i.group())
#8
#20191022
#59284
#2019
正则表达式的分组在re模块中的使用
s = '<a>wahahafsdfsfdafsaafs</a>' #标签语言HTML网页
ret = re.search('(<\w+>)(\w+)(</\w+>)',s)
print(ret.group()) #<a>wahahafsdfsfdafsaafs</a> 所有结果
print(ret.group(1)) #<a> 数字参数代表的是取对应分组中的内容 第一个分组中的
print(ret.group(2)) #wahahafsdfsfdafsaafs 第二个分组中内容
print(ret.group(3)) #</a>
正则表达式的分组在热模块中,为了findall也可以顺利取到分组中的内容,有一个特殊的语法,优先显示分组中的内容
s = '<a>wahahafs</a>'
ret = re.findall('(\w+)',s)
print(ret) #['a', 'wahahafs', 'a']
res = re.findall('>(\w+)<',s) #优先寻找匹配括号中的内容
print(res) #['wahahafs']
如果想取消分组优先
形式:(?:正则表达式)
ret = re.findall('\d+(\.\d+)','1.234*4')
print(ret) >>> ['.234']
ret = re.findall('\d+(?:\.\d+)','1.234*4') #取消了分组优先
print(ret) >>> ['1.234']
def parser_page(text):
res_list = re.findall(
'<div class="item">.*?<a href="(.*?)">.*?<span class="title">(.*?)</span>.*?<span class="rating_num".*?>(.*?)</span>.*?<span>(.*?)人评价',
text,
re.S)
for movie_tuple in res_list:
print(movie_tuple)
yield movie_tuple
匹配到最后
re.search("HuaHuoDingZhiVideoPrice=(.*?)+$", quotations)
匹配小数
def _try(func, return_type=None):
try:
return func()
except Exception as e:
logging.error(e)
print(e)
return return_type
# 匹配小数
res = _try(lambda : re.search("\d*(\.\d+)\d*", text, re.S).group(), '')
判断是否包含数字
bool(re.search(r'\d', str(build_area)))
re.findall(r'[\u4e00-\u9fa5]', a)
剔除乱码字符
只匹配一下字符
re.sub(u"([^\u4e00-\u9fa5\u0030-\u0039\u0041-\u005a\u0061-\u007a])","",string)
正则表达式说明
函数 | 说明 |
---|---|
sub(pattern,repl,string) | 把字符串中的所有匹配表达式pattern中的地方替换成repl |
[^**] | 表示不匹配此字符集中的任何一个字符 |
\u4e00-\u9fa5 | 汉字的unicode范围 |
\u0030-\u0039 | 数字的unicode范围 |
\u0041-\u005a | 大写字母unicode范围 |
\u0061-\u007a | 小写字母unicode范围 |
\uAC00-\uD7AF | 韩文的unicode范围 |
\u3040-\u31FF | 日文的unicode范围 |