http://tool.oschina.net/regex 在线正则表达式测试
常用方法
^ 开头$ 结尾\s 空格\d 数字\d{5} 5个数字\w 小写w 匹配字母+数字+下划线\W 大写 W 匹配非字母、非数字、非下划线. 匹配任意字符,除了换行符(但是在指定匹配模式 re.S的时候就可以)* 匹配0-多个字符+ 匹配一个或多个字符\s*? 匹配一个可能有,可能没有的空白字符\n 匹配一个换行符。等价于 \x0a 和 \cJ。
Jupyter Notebook
- pip install jupyter
- jupyter notebook 在命令行运行
re.match
尝试是字符串起始位置开始匹配的一个模式,如果匹配不成功,返回 Nonere.match(pattern,string,flags=0)
最常规的匹配
结果如下:import re#引入正则表达式库content = 'Hello 123 4567 World_This is a Regex Demo'print(len(content))result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)# 【第一个参数是正则表达式的规则】,【第二个参数是被匹配的内容】print(result)#打印匹配结果信息print(result.group())# group 表示只打印匹配出来的结果print(result.span())# 输出匹配结果的范围
泛匹配
结果和上面的是一样的。import recontent = 'Hello 123 4567 World_This is a Regex Demo'print(len(content))result = re.match('^Hello.*Demo$',content)# 泛匹配,匹配 Hello Demo 中间的所有内容。print(result)print(result.group())print(result.span())
匹配目标
import recontent = 'Hello 1234567 World_This is a Regex Demo'result = re.match('^Hello\s(\d+)\sWorld.*Demo$',content)# 我们需要匹配的是1234567# \d+ 表示匹配1个或多个数字# () 内为需要匹配的内容print(result)print(result.group(1))# group(1)表示第一个group,如果匹配规则有两个group,那第二个就是 group(2)print(result.span())
我们需要匹配的是1234567 \d+ 表示匹配1个或多个数字 () 内为需要匹配的内容 group(1)表示第一个group,如果匹配规则有两个group,那第二个就是 group(2)
贪婪模式
import recontent = 'Hello 1234567 World_This is a Regex Demo'result = re.match('^He.*(\d+).*Demo$',content)# .* 贪婪识别print(result)print(result.group(1))print(result.span())
结果如下,它只匹配到到了一个7, 因为(\d+)前面的 .*会匹配尽可能多的字符,而(\d+)是需要匹配至少一个,由于前面是贪婪的,所以(\d+)就只能得到一个数字了。
非贪婪模式
在
.*后面加一个”问号”,变成.*?就是匹配 尽量少 的字符。
import recontent = 'Hello 1234567 World_This is a Regex Demo'result = re.match('^He.*?(\d+).*Demo$',content)# .*? 非贪婪识别print(result)print(result.group(1))print(result.span())

这个时候结果就是1234567了 这个时候就让 (\d+) 尽量多的识别了字符
匹配模式(换行匹配)
import recontent = '''Hello 1234567 World_Thisis a Regex Demo'''# ''' 内容''' 是换行符的意思。如过按照上面的写法是无法匹配出结果的result = re.match('^He.*?(\d+).*Demo$',content,re.S)# 后面的re.S (大写 S)就可以让.匹配换行符了。print(result)print(result.group(1))print(result.span())
转义
import recontent = 'price is $5.00'result = re.match('price is \$5\.00',content)print(result)
在这里 $ 和. 需要在前面加一个 \ 来把他们转义成字符串。 这样匹配出来的就没有问题。
总结:
尽量使用泛匹配、使用括号的到匹配目标,尽量使用费贪婪模式,有换行符就用re.S
re.search
import recontent = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'result = re.match('Hello.*?(\d+).*?Demo',content)print(result)
我们从中间开始匹配,结果如下
但是如果把 match 改成 search
import recontent = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'result = re.search('Hello.*?(\d+).*?Demo',content)# 把 match 改成 searchprint(result)

这样就匹配成功了。
为了方便,能用search 就不用 match
匹配演练
import rehtml = '''<div id="songs-list"><h2 class="title">经典老歌</h2><p class="introduction">经典老歌列表</p><ul id="list" class="list-group"><li data-view="2">一路上有你</li><li data-view="7"><a href="/2.mp3" singer="任贤齐">沧海一声笑</a></li><li data-view="4" class="active"><a href="/3.mp3" singer="齐秦">往事随风</a></li><li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li><li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li><li data-view="5"><a href="/6.mp3" singer="邓丽君">但愿人长久</a></li></ul></div>'''result = re.search('<li.*active.*?singer="(.*?)">(.*?)</a>',html,re.S)if result: # 去掉也可以print(result.group(1),result.group(2))
结果如下,这里匹配的结果是 带 class= active 的标签,如果去掉 active 那就会匹配第一个
任贤齐 沧海一声笑
re.findall
import rehtml = '''<div id="songs-list"><h2 class="title">经典老歌</h2><p class="introduction">经典老歌列表</p><ul id="list" class="list-group"><li data-view="2">一路上有你</li><li data-view="7"><a href="/2.mp3" singer="任贤齐">沧海一声笑</a></li><li data-view="4" class="active"><a href="/3.mp3" singer="齐秦">往事随风</a></li><li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li><li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li><li data-view="5"><a href="/6.mp3" singer="邓丽君">但愿人长久</a></li></ul></div>'''results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)print(results)print(type(results))for result in results:print(result)print(result[0],result[1],result[2])
匹配出歌词
import rehtml = '''<div id="songs-list"><h2 class="title">经典老歌</h2><p class="introduction">经典老歌列表</p><ul id="list" class="list-group"><li data-view="2">一路上有你</li><li data-view="7"><a href="/2.mp3" singer="任贤齐">沧海一声笑</a></li><li data-view="4" class="active"><a href="/3.mp3" singer="齐秦">往事随风</a></li><li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li><li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li><li data-view="5"><a href="/6.mp3" singer="邓丽君">但愿人长久</a></li></ul></div>'''results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)# 第一个()和最后一个括号是匹配<a></a>, 因为一路上有你没有a标签,所有后面加个 ? 表示可能为0-多个。# \s*? 表示0-多个空格#print(results)for result in results:print(result[1])
re.sub
替换字符串中每一个匹配的子串后返回替换后的字符串。
import recontent = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'content = re.sub('\d','q',content)#如果只写 \d 就会 1-7每个数字替换一次。qqqqqqq 效果如图1# 如果写成\d+ 就会把1234567 替换成 q 效果如图2# 第一个参数传入正则表达式,第二个参数传入要替换的内容,第三个参数传入元内容。print(content)
包括内容再替换
import recontent = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'content = re.sub('(\d+)',r'\1 q',content)# 需要把替换内容放在一个小括号内,需要替换的内容要 r'\1' r是声明一下,然后\1表示前面的括号内容,再添加其他内容 包括空格就会一起替换 之前的 1234567print(content)
替换再findall
import rehtml = '''<div id="songs-list"><h2 class="title">经典老歌</h2><p class="introduction">经典老歌列表</p><ul id="list" class="list-group"><li data-view="2">一路上有你</li><li data-view="7"><a href="/2.mp3" singer="任贤齐">沧海一声笑</a></li><li data-view="4" class="active"><a href="/3.mp3" singer="齐秦">往事随风</a></li><li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li><li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li><li data-view="5"><a href="/6.mp3" singer="邓丽君">但愿人长久</a></li></ul></div>'''html = re.sub('<a.*?>|</a>','',html)#print(html)results = re.findall('<li.*?>(.*?)</li>', html, re.S)#print(results)for result in results:print(result.strip())#.strip()去掉换行符
re.compile
将一个正则表达式串编译成正则对象,以便于复用该匹配模式
import recontent = '''Hello 1234567 World_Thisis a Regex Demo'''pattern = re.compile('Hello.*Demo',re.S)result = re.match(pattern,content)# 先写一个正则表达式规则并且赋予 pattern ,#下次就不用写正则表达式规则了,直接在规则那输入 pattern 就调用了这个正则表达式规则。#result = re.match('Hello.*Demo',content,re.S)#上面个语句表达出来的意思等同这次print(result)
实战练习
import reimport requestscontent = requests.get('https://book.douban.com/').textpattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>', re.S)results = re.findall(pattern,content)#print(results)for result in results:url,name,author,date = result# 每个值是一个括号author = re.sub('\s','',author)date = re.sub('\s','',date)# author 和date 带换行符,取消掉print(url,name,author,date)#print(url,name,author.strip(),date.strip()) #等同于上面两行的效果
结果如下

