11-3 re模块

正则表达式,一般用于字符串匹配.

这里我们需要用到re模块来学习正则表达式.

r 的作用

print(r'\') # 原生字符,r后面字符串内的特殊符号没有意义,按正常的字符串输出
print('\\') # \ 转义

re模块的常用功能

findall

  • 返回值:列表 列表中是所有匹配到的项
  • ?:在有分组的情况下findall()函数,不只拿分组里的字符串,拿所有匹配到的字符串,注意?:只用于不是返回正则对象的函数如findall()
ret = re.findall('[a-z]+', 'eva egon yuan')
print(ret)
# 返回所有满足匹配条件的结果,放在列表里

# 空的匹配也会包含在结果中

# 获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
ret = re.search('a', 'eva egon yuan')
if ret:
    print(ret.group())
# 从前往后,找到一个就返回,返回的变量需要调用group才能拿到结果,结果是字符串类型
# 如果没有找到,那么返回None,调用group会报错
# 无分组

        r = re.search("a\w+", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组结果

        # 有分组

        r = re.search("a(\w+).*(?P<name>\d)$", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

demo

match

ret = re.match('[a-z]+', 'eva egon yuan')
if ret:
    print(ret.group())
# match是从头开始匹配,如果正则规则从头开始找匹配上第一个,就返回一个变量。
# 匹配的内容如果匹配上了 .group取值
# 如果没匹配上,就返回None,调用group会报错
# 无分组
        r = re.match("h\w+", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组结果

        # 有分组

        # 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)

        r = re.match("h(\w+).*(?P<name>\d)$", origin)
        print(r.group())     # 获取匹配到的所有结果
        print(r.groups())    # 获取模型中匹配到的分组结果
        print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

split

ret = re.split('[ab]', 'abcd')
# 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']

sub 将数字替换成'H'

import re
ret = re.sub('\d', 'H', 'eva3egon4yuan4',1)
# 将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4

subn 将数字替换成'H',返回元组(替换的结果,替换了多少次)

ret = re.subn('\d', 'H', 'eva3egon4yuan4')
#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)

compile 将正则表达式编译成为一个 正则表达式对象

正则表达式很长且要多次使用

obj = re.compile('\d{3}')
#将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())

finditer 返回一个存放匹配结果的迭代器

ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
# print(next(ret).group())  #查看第一个结果
# print(next(ret).group())  #查看第二个结果
# print([i.group() for i in ret])  #查看剩余的左右结果
for i in ret:
    print(i.group())

| 管道符

从左到右匹配,只要匹配上就不继续匹配了。所以应该把长的放前面

ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

() 分组

也就是分组匹配。()里面的做一个组也可以理解为一个整体。

如果()后面的跟的是特殊元字符如(adc)* 那么*控制的前导字符就是()里的整体内容,不在是前导一个字符。

ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")

# 还可以在分组中利用?P<key>的形式给分组起名字  <?P=key>
# 定义组里匹配内容的key(键),<>里面写key名称,值就是匹配到的内容(只对正则函数返回对象时有用)
    
# 获取的匹配结果可以直接用group('名字')拿到对应的值
ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")

# 如果不给组起名字,也可以用`\序号`来找到对应的组,表示要找的内容和前面的组内容一致

# 获取的匹配结果可以直接用group(序号)拿到对应的值

print(ret.group(1))
print(ret.group())  #结果 :<h1>hello</h1>
ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#re模块:分组是有优先的
                    # findall
                    # split

[]字符集

需要字符串里完全符合,匹配规则就匹配。对应位置是[]里的任意一个字符就匹配。

字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]

所有特殊字符在字符集中都失去了原有的特殊含义,用\反斜杠转义恢复特殊字符的特殊含义。

^在[]外面: 匹配的字符以...开头

^在[]里面 , 表示非,除了 [] 内的元素都匹配,取反

# [^] 除了字符组内字符的其他都匹配,表示 取反

{}范围

需要字符串里完全符合,匹配规则,就匹配(规则里的{})前面的一个字符,匹配这个字符n次。n可以自定义。

{m} 匹配前一个字符m次
{m,} 匹配前一个字符m至无限次
{m,n} 匹配前一个字符m至n次
{0,} 匹配前一个字符0次至无限次,相当于*
{1,} 匹配前一个字符1次至无限都,相当于+
{0,1} 匹配前一个字符0次至1次,相当于?

爬虫案例

import re
from urllib.request import urlopen

def getPage(url):
    response = urlopen(url)
    return response.read().decode('utf-8')

def parsePage(s):
    ret = re.findall(
        '<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
       '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>',s,re.S)
    return ret

def main(num):
    url = 'https://movie.douban.com/top250?start=%s&filter=' % num
    response_html = getPage(url)
    ret = parsePage(response_html)
    print(ret)

count = 0
for i in range(10):   # 10页
    main(count)
    count += 25

# url从网页上把代码搞下来
# bytes decode ——> utf-8 网页内容就是我的待匹配字符串
# ret = re.findall(正则,带匹配的字符串)  #ret是所有匹配到的内容组成的列表



作业--计算器

# 从括号里取值

a = '1 - 2 * ( ( 6 0 -3 0  +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
# 去掉所有的空格
# 加减乘除  括号
# 先算括号里的乘除,再算括号里的加减
# 从括号里取值 == 正则表达式
ss = '9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14'
# 从一个没有括号的表达式中取 */法  == 正则表达式


思路:
# 首先得到一个字符串
# 去空格
# 没有空格的字符串
# 先算最里层括号里的 : 找括号 ,且括号里没有其他括号
# 得到了一个没有括号的表达式 :只有加减乘除 从左到右先找到第一个乘除法   —— 重复
# 所有的乘除法都做完了
# 计算加减  —— 加减法
# 只有一个数了 就可以结束了

元字符

. 匹配除换行符以外的任意字符

\w 匹配字母或数字或下划线或汉字
# \W 匹配任何非字母数字下划线或汉字的字符
\s 匹配任意的空白符
# \S 匹配任意非空的字符
\d 匹配数字
# \D 匹配任意非数字的字符

\b 匹配单词的开始或结束

^ 匹配字符串的开始

$ 匹配字符串的结束

次数

* 重复0次或更多次

+ 重复1次或更多次

? 重复0次或1次

{n} 重复n次

{n,} 重复n次或更多次

{n,m} 重复n次到m次

惰性匹配

量词后面加 ?符号. 如.*?abc 一直取直到遇到abc就停止

猜你喜欢

转载自www.cnblogs.com/chenych/p/11082602.html