re库
re库用于是正则表达式的库,是python自带的库。
import re
直接引入即可使用。
设置匹配规则
re.compile()方法用于生成一个pattern对象,这个对象就是一个正则的规则。这个方法的参数是一个字符串,内写正则的规则。推荐使用原始字符串,使用过多转义字符的话程序可读性会变差。
正则表达式的规则如下:
. 匹配除换行符以外的任意字符
^ 匹配字符串的开始
$ 匹配字符串的结尾
* 匹配前面的子表达式零次或多次
+ 匹配前面的子表达式一次或多次
? 匹配前面的子表达式零次或一次
{n} n 是一个非负整数。匹配确定的 n 次
{n,} n 是一个非负整数。至少匹配n 次
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次
[xyz] 字符集合。匹配所包含的任意一个字符
[^xyz] 负值字符集合。匹配未包含的任意字符
\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_]'
示例:
import re
pattern = re.compile(r"\d+")
m1 = pattern.findall("one123two456three789")
print(m1) # ['123', '456', '789']
这里我们的规则是至少一个数字
pattern2 = re.compile(r"[a-zA-Z]+")
m2 = pattern2.findall("one123two456three789")
print(m2) # ['one', 'two', 'three']
这里的规则是至少一个字母
findall方法在后文
匹配
从头开始match
match方法的作用是从头开始匹配,只匹配一个结果,如果匹配不到则返回none
m1 = pattern.match("one123two456three789")
print(m1) #none
结果为none的原因是从第一个字符开始匹配,第一个字符不符合条件故返回none。
方法有三个参数,第一个是要匹配的字符串,第二个是起始匹配位置,第三个是结束匹配位置。第二三个参数可省略,省略后为匹配整个字符串。
m2 = pattern.match("one123two456three789",3,6)
# 通过group查看匹配的数据
print(m2)
print(m2.group())
这样我们用于匹配的实际字符串就是123t,匹配到了数据。
任意位置开始search
和match相似,不过开始位置换为了任意位置。
import re
pattern = re.compile(r"\d+")
m1 = pattern.search("one123two456three789")
print(m1)
print(m1.group()) # 123
它可以在字符串中寻找匹配的第一个数据,不再局限于一定要从第一个字符开始匹配。
他也有三个参数,参数列表和match一样。
匹配所有findall
findall是匹配所有的项目全都放到一个列表中。
import re
pattern = re.compile(r"\d+")
m1 = pattern.findall("one123two456three789")
print(m1) #['123', '456', '789']
print(type(m1)) # <class 'list'>
它的参数列表和match相同但是返回值类型不同,其它的返回的是对象这里返回的是列表,列表中是匹配到的字符串。
对象在目录中找到正则分组查看。
拆分split
import re
str1 = "a,b,c"
print(str1.split(",")) # ['a', 'b', 'c']
str2 = "a,b;; c d"
pattern = re.compile(r"[\s\,\;]")
# 按照正则匹配的字符进行拆分,这里的符号是空格,分号,逗号三种皆可
m1 = pattern.split(str1)
print(m1) # ['a', 'b', 'c']
print(type(m1)) # <class 'list'>
# re的split方法可以任意字符分割了,不像原始的split只局限于一种字符
split和原本的split类似,只是可以用自定义字符了,原版只局限于传入的那一种字符。
该方法的返回值也是list
正则分组
正则表达式相关方法有两种返回值,list和<class 're.Match'>,这种对象有一个group()方法可以返回正则匹配的内容。我们如果在正则表达式中添加括号则可以为结果分组,如下:
import re
str1 = '<h1 class="test">1Hello1world1</h1>'
pattern2 = re.compile(r'<(.\d)\sclass="(?P<classname>.*?)">.*?</(.1)>')
print(pattern2.search(str1).group(1))
print(pattern2.search(str1).group(2))
print(pattern2.search(str1).group("classname"))
print(pattern2.search(str1).group(3))
print(pattern2.search(str1).group())
其中 ?P<classname> 的作用是为这个分组起个名字。可以通过第几个组或组名来获取匹配到的数据。
替换sub
第一个参数是要换成的字符,第二个是被替换的字符串,第三个要替换几个。
第三个参数省略则为全部替换。
该方法可以将符合规则的字符替换成指定的字符。
import re
str1 = '<h1 class="test">1Hello1world1</h1>'
pattern = re.compile(r'\d')
print(pattern.sub("2",str1)) # <h2 class="test">2Hello2world2</h2>
print(pattern.sub("2",str1,1)) # <h2 class="test">1Hello1world1</h1>
print(pattern.sub("2",str1,2)) # <h2 class="test">2Hello1world1</h1>
print(pattern.sub("2",str1,3)) # <h2 class="test">2Hello2world1</h1>
第一个参数也可以是个方法:
sub方法中 参数1函数名,是对字符串的替换规则。参数2是要操作的字符串,将sub(str)的结果传入到第一个参数中,返回第一个参数的结果。
def func(m):
return "aftrt sub:" + m.group('classname')
print(pattern2.sub(func,str1)) # aftrt sub:test
将匹配的结果传入func方法中,对传入的数据操作,这个方法的内容就是替换规则。替换后的语句就是func的返回值。
爬虫中的应用
可以用正则匹配reponse.text中的内容获取标签,然后一点点截取需要的数据。如下:
item_search = re.compile(r'ts_solgcont_title">.*?<div class="ts_solistMrbot">',re.S)
# 匹配页面中的字符串
all_item = item_search.findall(content)
print(all_item)
title_search = re.compile(r'target="_blank">(.*?)</a>')
auther_search = re.compile(r'p>(.*?)</p>')
for item in all_item:
print({
"title":title_search.search(item).group(1),
"auther":auther_search.search(item).group(1)
})
访问的链接是http://www.cmpedu.com/so.htm?&KEY=java