正则表达式re

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替换列表中的多个特定单词

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值