1.正则表达式常见匹配模式:
模式 描述
\w 匹配字母数字及下划线
\W 匹配非字母数字下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9]
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
\z 匹配字符串结束
\G 匹配最后匹配完成的位置
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
* 匹配0个或多个的表达式。
+ 匹配1个或多个的表达式。
? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
{n} 精确匹配n个前面表达式。
{n,m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a|b 匹配a或b
( ) 匹配括号内的表达式,也表示一个组
[a-z] 匹配所有的小写字母
[A-Z] 匹配所有的大写字母
[a-zA-Z] 匹配所有的字母
[0-9] 匹配所有的数字
[0-9\.\-] 匹配所有的数字,句号和减号
[ \f\r\t\n] 匹配所有的白字符
1.re.match:尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
re.match(pattern, string, flags=0)
pattern:正则表达式
string:被匹配的字符串
flags:匹配模式,编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。(多条件匹配可以使用或运算符'|'表示,例如: flags=re.I | re.S)
注意: “|”两边不能有空格
常用的flags有:
标志 | 含义 |
re.S(DOTALL) | 使.匹配包括换行在内的所有字符 |
re.I(IGNORECASE) | 使匹配对大小写不敏感 |
re.L(LOCALE) | 做本地化识别(locale-aware)匹配,法语等 |
re.M(MULTILINE) | 多行匹配,影响^和$ |
re.X(VERBOSE) | 该标志通过给予更灵活的格式以便将正则表达式写得更易于理解 |
re.U | 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B |
获取匹配结果字符:
re.match(pattern,string,flags).group()
获取匹配结果字符长度:
re.match(pattern,string,flags).span()
1)常规匹配:
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())
print(result.span())
'''
41
<_sre.SRE_Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41)
'''
2)泛匹配: " .* " (匹配任意字符)
import re
content = 'Hello 123 4567 World_This is a Regex Demo'
result = re.match('^Hello.*Demo$', content)
print(result)
print(result.group())
print(result.span())
'''
<_sre.SRE_Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41)
'''
3)匹配目标(获取指定位置的字符)
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^Hello\s(\d+)\sWorld_This\s(\w+)\sa.*Demo$', content)
print(result)
print(result.group())
print(result.group(1))
print(result.group(2))
print(result.span())
'''
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>
Hello 1234567 World_This is a Regex Demo
1234567
is
(0, 40)
'''
4)贪婪匹配 (左边的泛匹配会尽可能多的匹配字符)
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^Hello\s\d+(\d+).*Demo$', content)
print(result)
print(result.group())
print(result.group(1))
'''
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>
Hello 1234567 World_This is a Regex Demo
7
'''
5)非贪婪匹配 "?" (左边的泛匹配会尽可能少的匹配字符)
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result = re.match('^Hell.*?(\d+).*Demo$', content)
print(result)
print(result.group())
print(result.group(1))
'''
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>
Hello 1234567 World_This is a Regex Demo
1234567
'''
6)flags 匹配模式
import re
content = '''Hello 1234567 World_This
is a Regex Demo'''
result = re.match('^Hell.*?(\d+).*Demo$', content,flags=re.S)
print(result)
print(result.group())
print(result.group(1))
'''
<_sre.SRE_Match object; span=(0, 41), match='Hello 1234567 World_This \nis a Regex Demo'>
Hello 1234567 World_This
is a Regex Demo
1234567
'''
多条件匹配,例如(同时匹配换行符并且忽略大小写)
import re
content = '''hello 1234567 World_This
is a Regex Demo'''
result = re.match('^Hell.*?(\d+).*Demo$', content,flags=re.I | re.S)
print(result)
print(result.group())
print(result.group(1))
'''
<_sre.SRE_Match object; span=(0, 41), match='hello 1234567 World_This \nis a Regex Demo'>
hello 1234567 World_This
is a Regex Demo
1234567
'''
7)转义 "\"
import re
content = 'price is $5.00'
result = re.match('price is $5.00', content)
print(result)
'''
None
'''
content = "value $1000.00"
result = re.match("^value\s(\$)\d{4}(\.)\d{2}", content, flags=re.I)
print(result)
print(result.group(1))
print(result.group(2))
'''
<_sre.SRE_Match object; span=(0, 14), match='value $1000.00'>
$
.
'''
2.re.search:扫描整个字符串并返回第一个成功的匹配。
总结:为匹配方便,能用search就不用match
re.search(pattern, string, flags=0)
匹配实例:
import re
html = '''<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.*?singer="(.*?)">(.*?)</a>', html, re.S)
if result:
print(result.group(1), result.group(2))
'''
任贤齐 沧海一声笑
'''
2.re.findall:搜索字符串,以列表形式返回全部能匹配的子串。
import re
html = '''<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.findall('''<li.*?<a.*?singer="(.*?)">(.*?)</a>''', html, flags=re.S)
print(result)
'''
[('任贤齐', '沧海一声笑'), ('齐秦', '往事随风'), ('beyond', '光辉岁月'), ('陈慧琳', '记事本'), ('邓丽君', '但愿人长久')]
'''
3.re.sub:替换字符串中每一个匹配的子串后返回替换后的字符串。
re.sub(pattern, repl, string, count=0)
注意: "|" 两边不能有空格
import re
content = '''not to
stop 123 until death'''
results = re.sub("\n\s*|\s\d+", "", content, re.I)
print(results)
'''
not to stop until death
'''
pattern 中的括号对应 repl 中的 '\1' '\2' '\3' ...
import re
content = "not to stop 123 until death"
results = re.sub("\s(stop)\s(\d+)", r" \2 \1", content, re.I)
print(results)
'''
not to 123 stop until death
'''
re.sub 和re.findall 联合使用
import re
htmls = '''<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>'''
htmls = re.sub("<a.*?>|</a>", "", htmls, re.S)
results = re.findall("<li.*?>\n?\s*(.*?)\n?\s*</li>", htmls, re.S)
for name in results:
print("name: ", name)
'''
name: 一路上有你
name: 沧海一声笑
name: 往事随风
name: 光辉岁月
name: 记事本
name: 但愿人长久
'''
4.re.compile:将正则字符串编译成正则表达式对象,以便重复使用。
import re
content = '''be released 12345 only by death '''
pattern = re.compile('\d{5}', re.I)
result = re.search(pattern, content)
#result = re.search('\s\d+', content, re.I)
print(result.group()) if result != None else print("None")
'''
<_sre.SRE_Match object; span=(12, 17), match='12345'>
'''
5.实战练习
import requests
import re
url = "https://movie.douban.com/chart"
response = requests.get(url)
htmls = response.content.decode()
# html = re.sub('<span.*?>|</span>', '', htmls)
results = re.findall('''<a class="nbg" href="(.*?)".*? <a.*?>(.*?)</a>.*?<p.*?>(.*?)</p>.*?rating_nums">(.*?)</span>''', htmls, re.S)
for url, name, introduce, rating_nums in results:
name = re.sub("\s*\n\s|<span.*?>|</span>|\s*", "", name)
print("url: ", url)
print("name: ", name)
print("introduce: ", introduce)
print("rating_nums: ", rating_nums)
print("------------------------------------")
'''
url: https://movie.douban.com/subject/27615441/
name: 网络谜踪/人肉搜寻(港)/人肉搜索(台)
introduce: 2018-01-20(圣丹斯电影节) / 2018-08-24(美国) / 2018-12-14(中国大陆) / 约翰·赵 / 米切尔·拉 / 黛博拉·梅辛 / 约瑟夫·李 / 萨拉·米博·孙 / 亚历克丝·杰恩·高 / 梅金·刘 / 刘卡雅 / 多米尼克·霍夫曼 / 西尔维亚·米纳西安 / 梅丽莎·迪斯尼...
rating_nums: 8.5
------------------------------------
url: https://movie.douban.com/subject/27102569/
name: 悲伤逆流成河/悲伤逆流成河电影版/CryMeaSadRiver
introduce: 2018-09-21(中国大陆) / 赵英博 / 任敏 / 辛云来 / 章若楠 / 朱丹妮 / 中国大陆 / 落落 / 104分钟 / 剧情 / 爱情 / 落落 Luo Luo / 郭敬明 Jingming Guo / 汉语普通话
rating_nums: 5.8
------------------------------------
url: https://movie.douban.com/subject/27172891/
name: 大象席地而坐/金羊毛/爱在樱花盛开时
introduce: 2018-02-16(柏林电影节) / 彭昱畅 / 章宇 / 王玉雯 / 李从喜 / 董向荣 / 王柠 / 赵燕国彰 / 朱颜曼滋 / 凌正辉 / 王超北 / 王雪洋 / 中国大陆 / 胡波 / 230分钟(导演剪辑版) / 剧情 / 胡迁 Qian Hu / 汉语普通话
rating_nums: 8.1
------------------------------------
url: https://movie.douban.com/subject/26336252/
name: 碟中谍6:全面瓦解/碟中谍6/不可能的任务:全面瓦解(台)
introduce: 2018-07-27(美国) / 2018-08-31(中国大陆) / 汤姆·克鲁斯 / 亨利·卡维尔 / 文·瑞姆斯 / 西蒙·佩吉 / 丽贝卡·弗格森 / 西恩·哈里斯 / 安吉拉·贝塞特 / 凡妮莎·柯比 / 米歇尔·莫纳汉 / 韦斯·本特利 / 费雷德里克·施密特 / 亚历克·鲍德温...
rating_nums: 8.2
......
'''