re.match(正则表达式,要匹配的字符串,flags)
# match从头开始匹配
# re.match默认配置以xxx开头的字符串,所以正则中的^符号可省略不写
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
# flags是标致位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
实例1:匹配某个字符
import re
text = 'hello'
ret = re.match('he', text)
print(ret) # 如果没有匹配字符,这里返回None
print(ret.group()) # 返回匹配的结果;如果没有匹配字符,这里会抛异常
#
# he
实例2:点匹配任意一个字符
text = 'hello'
ret = re.match('.', text)
print(ret.group()) # h
注意:点不能匹配换行符
实例3:\d匹配任意数字
text = '1231564hello'
ret = re.match('\d', text)
print(ret.group()) # 1
实例4:\D匹配任意非数字
text = '+hello'
ret = re.match('\D', text)
print(ret.group())
实例5:\s匹配空白字符
# \n, \t, \r及空格
text = '\thello'
ret = re.match('\s', text)
print(ret.group())
实例6:判断列表中元素是否符合变量规范
import re
def main():
names = ["age", "_age", "1age", "age1", "a_age", "age_1_", "age!", "a#123"]
for i in names:
ret = re.match(r"[a-zA-Z_]\w*$", i) # match默认以^匹配开头,所以^符号可以不写
if ret:
print('变量名:%s 符合要求;通过正则匹配出的数据是:%s' % (i, ret.group()))
else:
print('变量名:%s 不符合要求' % i)
if __name__ == '__main__':
main()
实例7:re.match()取分组数据
import re
def main():
email = input('Please input a email: ')
ret = re.match(r"[a-zA-Z0-9_]{4,20}@(163|126)\.com$", email)
print(ret.group()) # 取得匹配到的值
print(ret.group(1)) # 取得第一个分组(上面括号里的数据)数据
# 如果正则中只有一个分组,而ret.group(2)取数据会报IndexError: no such group异常
if ret:
print('OK')
else:
print('Not email')
if __name__ == '__main__':
main()
re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
ret = re.search(r"\d+", "阅读次数为 9999;点赞次数为 87878")
print(ret.group()) # 9999
findall(pattern, string, flags=0)
# 返回string中所有与pattern相匹配的全部字串,返回形式为列表
ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
print(ret)
# ['9999', '7890', '12345']
titles = re.findall(r'.*(.*)', text, re.DOTALL)
# .不匹配\n,后面加上re.DOTALL,表示.也要匹配\n
re.findall()在匹配时分组与不分组的区别
import re
string="abcdefg acbdgef abcdgfe cadbgfe"
#带括号与不带括号的区别
#不带括号
regex=re.compile("((\w+)\s+\w+)")
print(regex.findall(string))
#输出:[('abcdefg acbdgef', 'abcdefg'), ('abcdgfe cadbgfe', 'abcdgfe')]
regex1=re.compile("(\w+)\s+\w+")
print(regex1.findall(string))
#输出:['abcdefg', 'abcdgfe']
regex2=re.compile("\w+\s+\w+")
print(regex2.findall(string))
#输出:['abcdefg acbdgef', 'abcdgfe cadbgfe']
第一个 regex 中是带有2个括号的,我们可以看到其输出是一个list 中包含2个 tuple
第二个 regex 中带有1个括号,其输出的内容就是括号匹配到的内容,而不是整个表达式所匹配到的结果。
第三个 regex 中不带有括号,其输出的内容就是整个表达式所匹配到的内容。
结论:findall()返回的是括号所匹配到的结果(如regex1),多个括号就会返回多个括号分别匹配到的结果(如regex),如果没有括号就返回就返回整条语句所匹配到的结果(如regex2)。所以在提取数据的时候就需要注意这个坑。
2.4 re.sub()
将匹配到的数据进行替换
re.sub(pattern, repl, string, count=0, flags=0)
# 第一个参数pattern:就是正则式字符串或者正则式对象
# 第二个参数repl:就是要用什么东西去替换pattern匹配到的字符串(这里也可以是一个函数)
# 第三个参数string:就是对哪个字符串进行匹配与替换
# 第四个参数count:就是只替换前几个,如果是0则全部都替换
re.sub()简单使用:
ret = re.sub(r"\d+", '100', 'python = 666, c++ = 1024')
print(ret)
# python = 100, c++ = 100
re.sub()使用函数:
def add(temp):
strNum = temp.group()
num = int(strNum) + 1
return str(num)
ret = re.sub(r"\d+", add, "python = 666")
print(ret)
# python = 667
2.5 re.split()
根据匹配进行切割字符串,并返回一个列表
re.split()简单使用
ret = re.split(r":| ","info:xiaoZhang 33 shandong") # 以冒号或者空格切割,也可以使用[: ]
print(ret)
# ['info', 'xiaoZhang', '33', 'shandong']
使用括号捕获分组,默认保留分割符
ret = re.split(r"([:])","info:xiaoZhang 33 shandong")
print(ret)
# ['info', ':', 'xiaoZhang 33 shandong']
不想保留分隔符,以(?:…)的形式指定
ret = re.split(r"(?:[:])","info:xiaoZhang 33 shandong")
print(ret)
# ['info', 'xiaoZhang 33 shandong']
re.compile写法:
import re
one = 'adkfjklsdjflksd'
pattern = re.compile('s')
result = pattern.split(one)
print(result) # ['adkfjkl', 'djflk', 'd']
三:贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
非贪婪则相反,总是尝试匹配尽可能少的字符。
在 “*” , “?” , “+” , “{m,n}” 后面加上?,使贪婪变成非贪婪。
>>> s="This is a number 234-235-22-423"
>>> r=re.match(".+(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'4-235-22-423'
>>> r=re.match(".+?(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'234-235-22-423'
正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。
解决方式:非贪婪操作符“?”,这个操作符可以用在"*","+","?"的后面,要求正则匹配的越少越好。
>>> re.match(r"aa(\d+)","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)
'2'
>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)
'2343'
四:小案例
1:python爬虫抓取网页文章
import re
import requests
def parse_page(url):
headers = {'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
response = requests.get(url, headers=headers)
text = response.content.decode()
titles = re.findall(r'(.*)', text)
befrom = re.findall(r'(.*)', text)
author = re.findall(r'', text)
contents = re.findall(r'(.*?)', text, re.DOTALL)
contents = [re.sub(r'<.*?>', '', content).strip() for content in contents]
a = [{'title': titles[i], 'befrom': befrom[i], 'author': author[i], 'content': contents[i]} for i in range(len(titles))]
print(a)
def main():
url = 'https://www.gushiwen.org/default_1.aspx'
parse_page(url)
if __name__ == '__main__':
main()
2:匹配中文字符
import re
one = 'adq我kfjkl是sdj谁flksd'
pattern = re.compile('[\u4e00-\u9fa5]') # Python中匹配中文字符的unicode范围
result = pattern.findall(one)
print(result) # ['我', '是', '谁']