上一篇给人人解说的是爬虫的剖析体式格局二:Beautifulsoup,本日给带给人人的是正则表达式。
正则表达式
正则表达式是一个迥殊的字符序列,它能协助你轻易的搜检一个字符串是不是与某种形式婚配。就是 事前定义好的一些特定字符、及这些特定字符的组合,构成一个“划定规矩字符”,这个“划定规矩字符” 来表达对字符的一种过滤逻辑。
正则并非python独占的,其他言语也都有正则。
python中的正则,封装了re模块
Python中经常运用的正则表达式处置惩罚函数
re.match函数
re.match 尝试从字符串的肇端位置婚配一个形式,假如不是肇端位置婚配胜利的话,match()就返回none。
函数语法:
re.match(pattern, string, flags=0)
函数参数申明:
参数 形貌
pattern 婚配的正则表达式
string 要婚配的字符串。
flags 标志位,用于掌握正则表达式的婚配体式格局,如:是不是辨别大小写,多行婚配等等。
婚配胜利re.match要领返回一个婚配的对象,不然返回None。
我们能够运用group(num) 或 groups() 婚配对象函数来猎取婚配表达式。
婚配对象要领 形貌
group(num=0) 婚配的全部表达式的字符串,group() 能够一次输入多个组号,
在这类状况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含一切小组字符串的元组,从 1 到 所含的小组号。
import re print(re.match('www', 'www.baidu.com').span()) # 在肇端位置婚配 print(re.match('com', 'www.baidu.com')) # 不在肇端位置婚配
以上实例运转输出效果为:
(0, 3) None
import re content = "Cats are smarter than dogs" result = re.match( r'(.*) are (.*?) .*', content) print(result.group()) print(result.group(1)) print(result.group(2))
以上实例实行效果以下:
Cats are smarter than dogs Cats smarter result.group()猎取婚配的效果 result.span()获去婚配字符串的长度局限
泛婚配
实在相对来说上面的体式格局并非异常轻易,实在能够将上述的正则划定规矩举行变动
import re content = "Cats are smarter than dogs" result = re.match( r'Cats.*dogs$', content) print(result) print(result.group()) print(result.span())
婚配目的
假如为了婚配字符串中细致的目的,则须要经由过程()括起来,例子以下:
import re content = "Cats are 1234567 smarter than dogs" result = re.match( r'(.*)\sare\s(\d+)\s(.*?)\s.*', content) #\s婚配空格符 \d+婚配数字 print(result.group()) print(result.group(1)) print(result.group(2))
以下为实行效果:
Cats are smarter than dogs
Cats
1234567
贪欲婚配
先看下面代码:
import re content = "Cats are 1234567 smarter than dogs" result = re.match( r'Cats.*(\d+).*dogs', content) print(result.group()) print(result.group(1))
从效果中能够看出只婚配到了7,并没有婚配到1234567,涌现这类状况的原因是前面的.* 给婚配掉了, .*在这里会尽能够的婚配多的内容,也就是我们所说的贪欲婚配,
假如我们想要婚配到1234567则须要将正则表达式改成:
result = re.match( r'Cats.*?(\d+).*dogs', content)
如许效果就能够婚配到1234567
婚配形式
很多时刻婚配的内容是存在换行的题目的,这个时刻的就须要用到婚配形式re.S来婚配换行的内容
import re content = """Cats are 1234567 smarter than dogs dogs are wangwangwang""" result = re.match( r'Cats.*(\d+).*wangwangwang', content,re.S) print(result.group()) print(result.group(1))
转义
当我们要婚配的内容中存在迥殊字符的时刻,就须要用到转移标记\,例子以下:
import re content= "price is $5.00" result = re.match('price is \$5\.00',content) print(result.group())
注重:
对上面的一个小结:
只管运用泛婚配,运用括号获得婚配目的,只管运用非贪欲形式,有换行符就用re.S
强调re.match是从字符串的肇端位置婚配一个形式
re.search要领
re.search 扫描全部字符串并返回第一个胜利的婚配。
函数语法:
re.search(pattern, string, flags=0)
函数参数申明:
参数 形貌
pattern 婚配的正则表达式
string 要婚配的字符串。
flags 标志位,用于掌握正则表达式的婚配体式格局,如:是不是辨别大小写,多行婚配等等。
婚配胜利re.search要领返回一个婚配的对象,不然返回None。
我们能够运用group(num) 或 groups() 婚配对象函数来猎取婚配表达式。
婚配对象要领 形貌
group(num=0) 婚配的全部表达式的字符串,group() 能够一次输入多个组号,
在这类状况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含一切小组字符串的元组,从 1 到 所含的小组号。
import re content = "extra things hello 123455 world_this is a Re Extra things" result = re.search("hello.*?(\d+).*?Re",content) print(result.group()) print(result.group(1)
实在这个时刻我们就不须要在写^以及$,因为search是扫描全部字符串
注重:所以为了婚配轻易,我们会更多的用search,不必match,match必需婚配头部,所以很多时刻不是迥殊方
re.match与re.search的区分
re.match只婚配字符串的最先,假如字符串最先不相符正则表达式,则婚配失利,函数返回None;而re.search婚配全部字符串,直到找到一个婚配。
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>'''
import re result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html,re.S) print(result.group(1), result.group(2))
观察到<ul>节点内里有很多<li>节点,个中<li>节点有的包含<a>节点,有的不包含<a>节点,<a>节点另有一些响应的属性,超链接和歌手名。
起首我们尝试提取class为active的<li>节点内部的超链接包含的歌手名和歌名。
所以我们须要提取第三个<li>节点下的<a>节点的singer属性和文本。
所以正则表达式能够以<li>开首,然后接下来寻觅一个标志符active,中心的部份能够用.*?来婚配,然后接下来我们要提取singer这个属性值,所以还须要写入singer="(.*?)",我们须要提取的部份用小括号括起来,以便于用group()要领提取出来,它的两侧边境是双引号,然后接下来还须要婚配<a>节点的文本,那末它的左边境是>,右侧境是</a>,所以我们指定一下摆布边境,然后目的内容依旧用(.*?)来婚配,所以末了的正则表达式就变成了<li.*?active.*?singer="(.*?)">(.*?)</a>',然后我们再挪用search()要领,它便会搜刮全部HTML文本,找到相符正则表达式的第一个内容返回。
别的因为代码有换行,所以这里第三个参数须要传入re.S
注重:在上面两次婚配中,search()要领的第三个参数我们都加了re.S,使得.*?能够婚配换行,所以含有换行的<li>节点被婚配到了,假如我们将其去掉,只会婚配到不换行的的内容
re.findall
搜刮全部字符串然后返回婚配正则表达式的一切内容
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>'''
import re results = re.findall('<li.*?href="/(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S) for result in results: print(result) print(result[0], result[1], result[2])
运转效果:
('2.mp3', '任贤齐', '沧海一声笑')
2.mp3 任贤齐 沧海一声笑
('3.mp3', '齐秦', '旧事随风')
3.mp3 齐秦 旧事随风
('4.mp3', 'beyond', '辉煌光阴')
4.mp3 beyond 辉煌光阴
('5.mp3', '陈慧琳', '记事本')
5.mp3 陈慧琳 记事本
('6.mp3', '邓丽君', '但愿人长久')
6.mp3 邓丽君 但愿人长久
results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S) for result in results: #print(result) print(result[0], result[1], result[2])
运转效果:
一起上有你
<a href="/2.mp3" singer="任贤齐"> 沧海一声笑 </a>
<a href="/3.mp3" singer="齐秦"> 旧事随风 </a>
<a href="/4.mp3" singer="beyond"> 辉煌光阴 </a>
<a href="/5.mp3" singer="陈慧琳"> 记事本 </a>
<a href="/6.mp3" singer="邓丽君"> 但愿人长久 </a>
\s*? 这类用法实在就是为了处理有的有换行,有的没有换行的题目
(<a.*?>)? 这类用法是因为html中有的有a标签,有的没有的,?示意婚配一个或0个,恰好能够用于婚配
检索和替代
Python 的re模块供应了re.sub用于替代字符串中的婚配项。
语法:
re.sub(pattern, repl, string, count=0)
参数:
pattern : 正则中的形式字符串。
repl : 替代的字符串,也可为一个函数。
string : 要被查找替代的原始字符串。
count : 形式婚配后替代的最大次数,默许 0 示意替代一切的婚配。
import re phone = "2004-959-559 # 这是一个电话号码" # 删除解释 num = re.sub(r'#.*$', "", phone) print ("电话号码 : ", num) # 移除非数字的内容 num = re.sub(r'\D', "", phone) print ("电话号码 : ", num)
在这里我们只须要在第一个参数传入\D来婚配一切的数字,然后第二个参数“”是替代成的字符串,要去掉的话就能够赋值为空,第三个参数phone就是原字符串。
re.compile
将正则表达式编译成正则表达式对象,轻易复用该正则表达式
import re content= "hello world fan" pattern =re.compile("hello.*fan",re.S) result1 = re.match(pattern,content) result2 = re.search(pattern,content) result3 = re.sub(pattern, '', content) print(result1, result2, result3)
compile()还能够传入修饰符,比方re.S等修饰符,如许在search()、findall()等要领中就不须要额别传了。所以compile()要领能够说是给正则表达式做了一层封装,以便于我们更好地复用。
正则表达式修饰符 - 可选标志
正则表达式能够包含一些可选标志修饰符来掌握婚配的形式。修饰符被指定为一个可选的标志。多个标志能够经由过程按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 形貌
re.I 使婚配对大小写不敏感
re.L 做本地化辨认(locale-aware)婚配
re.M 多行婚配,影响 ^ 和 $
re.S 使 . 婚配包含换行在内的一切字符
re.U 依据Unicode字符集剖析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志经由过程赋予你更天真的花样以便你将正则表达式写得更易于明白。
正则表达式形式
形式字符串运用迥殊的语法来示意一个正则表达式:
字母和数字示意他们自身。一个正则表达式形式中的字母和数字婚配一样的字符串。
多半字母和数字前加一个反斜杠时会具有差别的寄义。
标点标记只要被转义时才婚配自身,不然它们示意迥殊的寄义。
反斜杠自身须要运用反斜杠转义。
因为正则表达式一般都包含反斜杠,所以你最好运用原始字符串来示意它们。形式元素(如 r'\t',等价于 \\t )婚配响应的迥殊字符。
下表列出了正则表达式形式语法中的迥殊元素。假如你运用形式的同时供应了可选的标志参数,某些形式元素的寄义会转变。
形式 形貌
^ 婚配字符串的开首
$ 婚配字符串的末端。
. 婚配恣意字符,除了换行符,当re.DOTALL标记被指定时,则能够婚配包含换行符的恣意字符。
[...] 用来示意一组字符,零丁列出:[amk] 婚配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 婚配除了a,b,c之外的字符。
re* 婚配0个或多个的表达式。
re+ 婚配1个或多个的表达式。
re? 婚配0个或1个由前面的正则表达式定义的片断,非贪欲体式格局
re{ n}
re{ n,} 准确婚配n个前面表达式。
re{ n, m} 婚配 n 到 m 次由前面的正则表达式定义的片断,贪欲体式格局
a| b 婚配a或b
(re) G 婚配括号内的表达式,也示意一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的地区。
(?-imx) 正则表达式封闭 i, m, 或 x 可选标志。只影响括号中的地区。
(?: re) 相似 (...), 然则不示意一个组
(?imx: re) 在括号中运用i, m, 或 x 可选标志
(?-imx: re) 在括号中不运用i, m, 或 x 可选标志
(?#...) 解释.
(?= re) 前向一定界定符。假如所含正则表达式,以 ... 示意,在当前位置胜利婚配时胜利,
不然失利。但一旦所含表达式已尝试,婚配引擎基础没有进步;
形式的盈余部份还要尝试界定符的右侧。
(?! re) 向前否认界定符。与一定界定符相反;当所含表达式不能在字符串当前位置婚配时胜利
(?> re) 婚配的自力形式,省去回溯。
\w 婚配字母数字
\W 婚配非字母数字
\s 婚配恣意空缺字符,等价于 [\t\n\r\f].
\S 婚配恣意非空字符
\d 婚配恣意数字,等价于 [0-9].
\D 婚配恣意非数字
\A 婚配字符串最先
\Z 婚配字符串完毕,假如是存在换行,只婚配到换行前的完毕字符串。c
\z 婚配字符串完毕
\G 婚配末了婚配完成的位置。
\b 婚配一个单词边境,也就是指单词和空格间的位置。
比方, 'er\b' 能够婚配"never" 中的 'er',但不能婚配 "verb" 中的 'er'。
\B 婚配非单词边境。'er\B' 能婚配 "verb" 中的 'er',但不能婚配 "never" 中的 'er'。
\n, \t, 等. 婚配一个换行符。婚配一个制表符。等
\1...\9 婚配第n个分组的内容。
\10 婚配第n个分组的内容,假如它经婚配。不然指的是八进制字符码的表达式。
正则表达式实例
字符婚配
实例 形貌
python 婚配 "python".
字符类
实例 形貌
[Pp]ython 婚配 "Python" 或 "python"
rub[ye] 婚配 "ruby" 或 "rube"
[aeiou] 婚配中括号内的恣意一个字母
[0-9] 婚配任何数字。相似于 [0123456789]
[a-z] 婚配任何小写字母
[A-Z] 婚配任何大写字母
[a-zA-Z0-9] 婚配任何字母及数字
[^aeiou] 除了aeiou字母之外的一切字符
[^0-9] 婚配除了数字外的字符
迥殊字符类
实例 形貌
. 婚配除 "\n" 之外的任何单个字符。要婚配包含 '\n' 在内的任何字符,请运用象 '[.\n]' 的形式。
\d 婚配一个数字字符。等价于 [0-9]。
\D 婚配一个非数字字符。等价于 [^0-9]。
\s 婚配任何空缺字符,包含空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 婚配任何非空缺字符。等价于 [^ \f\n\r\t\v]。
\w 婚配包含下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 婚配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
以上就是爬虫的剖析体式格局三:正则表达式的细致内容,更多请关注ki4网别的相干文章!