文章目录

  • ​​1. 正则字符​​
  • ​​2. 提取函数​​
  • ​​re.findall​​
  • ​​re.compile​​
  • ​​re.match和 re.search​​
  • ​​re.split()​​
  • ​​re.escape()​​
  • ​​练习1​​
  • ​​练习2​​
  • ​​练习3​​
  • ​​练习4-批量替换​​

1. 正则字符

字符

含义

​.​

代表除换行符以外的任何一个字符,可以用很多替代​​[\S\s]​​​ ​​[\W\w]​

​*​

代表它前面的一个子表达式0次到无限次

​?​

表示它前面的子表达式0次或1次

​+​

匹配前面的子表达式1次或多次

​\​

反斜杠把特殊字符变成普通符号如:\n换行符 \t制表符 \普通的反斜杠 '单引号 \d数字

​()​

可以把括号里面的内容提取出来

​[]​

集合字符,例如​​[a-zA-Z]​

​|​

表示或,​​[a-zA-Z]|[0-9]​​​ 表示满足数字或字母就可以匹配,这个规则等价于 ​​[a-zA-Z0-9]​​。

​^ $​

匹配字符串开头和结尾,在​​“[]”​​​内时含义不同,​​“[^]”​​​匹配集合之外的元素。匹配函数都有个​​flags​​​参数,当加上​​re.M​​表示多行匹配行首或行尾

​.*?​

爬虫开发常用字符组合,表示匹配一个能满足要求的最短字符串,这与​​.*​​​相对,通常,给定一个条件例如字符串为“密码是:123,密码是:456”,如果采用​​“密码是:(.*)”​​​,提取的是​​“123,密码是:456”​​​,而采用​​密码是:(.*?)​​,提取的则是[“123”,“456”] 两个数据

​\S​

匹配任何非空白字符。就是 \s 取非。如果设置了 ASCII 标志,就相当于 [^ \t\n\r\f\v],​​^​​在集合内表示取反

​\s​

匹配任何Unicode空白字符,包括 [ \t\n\r\f\v]

​\w​

字母数字下划线 [a-zA-Z0-9_]

​\W​

字母数字下划线以外的字符 [^a-zA-Z0-9_]

​[\u4e00-\u9fa5]​

匹配所有的汉字 (py2里 ​​[一-龥]​​匹配所有的汉字)

​()〈〉《》「」『』﹃﹄〔〕…—~﹏¥、【】,。?!:;“”‘​

中文标点符号

2. 提取函数

re.findall

​re.findall​​返回匹配值的列表

s = ‘I have a dog , I have a cat’
re.findall( r’I have a (?:dog|cat)’ , s )
['I have a dog', 'I have a cat']

re.compile

​compile(pattern, flags=0)​​第一个参数是字符串规则,第二个参数flags是匹配模式。返回一个模式对象
结合上面的​​​re.findall()​

import re  
s = "adfad asdfasdf asdfas asdfawef asd adsfas "

reObj1 = re.compile('((\w+)\s+\w+)')
reObj1.findall(s)
[('adfad asdfasdf', 'adfad'), ('asdfas asdfawef', 'asdfas'), ('asd adsfas', 'asd')]

reObj2 = re.compile('(\w+)\s+\w+')
reObj2.findall(s)
['adfad', 'asdfas', 'asd']

reObj3 = re.compile('\w+\s+\w+')
reObj3.findall(s)
['adfad asdfasdf', 'asdfas asdfawef', 'asd adsfas']

​pattern​​对象还可以用于split多字符分割字符串

split_re = re.compile(r'&|\-|\+')
split_re.split('a&b&c-d-1+2+3')
['a', 'b', 'c', 'd', '1', '2', '3']

re.match和 re.search

​match​​​从字符串的开头开始匹配,如果开头位置没有匹配成功,就算失败了;而​​search​​​会跳过开头,继续向后寻找是否有匹配的字符串。根据需要,可以灵活使用这两个函数。
search简单实用

x = re.search(r'(www)(\.r)', 'www.runoob.comwww')
x.group()
>>'www.r'
x.group(1)
>>'www'
x.group(2)
>>'.r'
x.groups()
>>('www', '.r')
# 返回匹配的位置,如果返回None,span会报错
re.search(r'(www)', 'www.runoob.comwww').span()
>>(0, 3)
s= 'Tom:9527 , Sharry:03'
m=re.match( r'(?P<name>\w+):(?P<num>\d+)', s)
m.group()
m.groups()
m.group(‘name’)
# 可以给数字加个字数限定
m=re.match( r'(?P<name>\w+):(?P<num>\d{4,})', s) # 表示匹配至少4个数字

用search提取指定的字符串,并做转换。这里是将url的文字部分转码成ASCII用于访问链接(quote是一个转换函数)

url = 'http://baike.baidu.com/item/秒懂大师说'
m = re.search(r'(.*?/item/)(.*)',url)
url = m.group(1)+quote(m.group(2))

re.split()

​re.split​​​按集合里的任意字符拆分
直接上一个复杂点的例子吧,前面学到​​​^​​​在​​[]​​中表示取非,则下面表示用除了汉子和字母数字以外的字符切分字符串s

s = "看上去很完美——计算量少了,功能更强了。实际效果如何呢?"
l = re.split('[^\u4e00-\u9fa50-9a-zA-Z]+', s)
>> ['看上去很完美', '计算量少了', '功能更强了', '实际效果如何呢', '']
re.split('([^\u4e00-\u9fa50-9a-zA-Z]+)', s) # 加括号保留分隔符
>> ['看上去很完美', '——', '计算量少了', ',', '功能更强了', '。', '实际效果如何呢', '?', '']

​Python 中re.split()方法​

re.escape()

因为有的时候我们需要使用一些特殊符号如”$ * . ^”等的原意,一个个转义字符很繁琐,​​re.escape()​​可以对字符串中所有可能被解释为正则运算符的字符进行转义。

re.escape('www.python.org')
'www\\.python\\.org'

这里举个例子,匹配一段文本的字符串并替换成指定的内容

def asr_to_correct(text):
rep = dict((re.escape(k), v) for k, v in error_asr_map.items())
pattern = re.compile("|".join(rep.keys()))
text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)
return text

​​python正则表达式 re (二)escape​​正则实现对一段文本同时匹配多个字符串

练习1

s =“1113446777”
用正则表达式把s分为1111, 3, 44, 6, 777
尝试re.findall(),发现不可行,search只会匹配第一次,所以也不可行

re.findall(r'(\d)\1*',s)
>> ['1', '3', '4', '6', '7']

m=re.finditer(r'(\d)\1*',s)
for i in m:
print(i.group())
>>
111
3
44
6
777

原理是什么我也不清楚,只是偶然看到
​Python中re的match、search、findall、finditer区别​​

练习2

这里假定给出一段贴吧源代码,我们想要提取其中的用户名、回复内容和回复时间。我们找到每一个楼层的开始代码为’l_post l_post_bright j_l_post clearfix’,结束代码为’p_props_tail props_appraise_wrap’

every_reply = re.findall('l_post l_post_bright j_l_post clearfix "(.*?)p_props_tail props_appraise_wrap',source,re.S) # re.S忽略换行符
for each in every_reply:
result = {}
result["username"] = re.findall('username="(.*?)"',each,re.S)[0]
result["content"] = re.findall('j_d_post_content ">(>*?)<"',each,re.S)[0].replace(' ','')
result["reply_time"] = re.findall('class="tail-info">(2017.*?)<',each,re.S)[0]

练习3

​re.sub​​替换匹配的一部分,替换多个标点符号,只保留第一个标点符号。

# 保留第一个捕获组,后面为''
re.sub(u'([?。!,])([?,。!]{1,})', u'\\1', u'?。!,。?')

u'?'

练习4-批量替换

替换英文字符为中文字符

>>>s = '你好,欢迎回家!?'
>>>l = ['\?','\!','\,','\.']
>>>d = {',':',','!':'!','?':'?', '.':'。'}
>>>re.sub(rf"({'|'.join(l)})", lambda mo: d[mo.group(1)], s)
'你好,欢迎回家!?'

参考
​​python正则表达式匹配 模式匹配​​Python 正则表达式验证浮点数
​regex-如何用python re.sub只替换部分匹配​​pythonlambda函数替换列表,Python:使用re.sub替换列表中的多个特定单词