day17

1. re模块的基础方法

# import re
# regex(正则表达式)

# compile
# re.compile(pattern[, flags])
# 作用:将正则表达式 pattern 编译为正则表达式对象,可用于使用其 match() 和search() 方法进行匹配。
# ret = re.compile(pattern), res = ret.findall(string) 
#    (等价于)
# ↓↓
# res = re.findall(pattern, string)

# flags定义包括:
  # re.I:忽略大小写
  # re.L:表示特殊字符集 w, W, , B, s, S 依赖于当前环境
  # re.M:多行模式
  # re.S:’ . ’并且包括换行符在内的任意字符(注意:’ . ’不包括换行符)
  # re.U: 表示特殊字符集 w, W, , B, d, D, s, S 依赖于 Unicode 字符属性数据库

# 1. 查找方法
# findall(pattern,string,flags = 0): 匹配所有,每一项都是列表中的一个元素 # ret = re.findall('d+','sdadsa172节食加胡斐928') # 正则表达式,待匹配的字符串,flag # ret = re.findall('d','sdadsa172节食加胡斐928') # 正则表达式,待匹配的字符串,flag # print(ret) # search(pattern,string,flags = 0): 只匹配从左到右的第一个,得到的不是直接的结果,而是一个变量,通过这个变量的group方法来获取结果 # 如果没有匹配到,会返回None,使用group会报错 # ret = re.search('d+','sddsa172节食加胡斐928') # print(ret) # 返回的是内存地址,这是一个正则匹配的结果 # print(ret.group()) # 通过ret.group()获取真正的结果 # # ret = re.search('d', "orweirjuqhnqd") # print(ret) # None # print(ret.group()) # 报错 # # ret = re.search('d+','sddsa172节食加胡斐928') # if ret: # 如果ret不是None(False) # print(ret.group()) # 通过ret.group()获取真正的结果 # match: 从头开始匹配,相当于search中的正则表达式加上一个^ # ret = re.match('d+','172sdadsa节食加胡斐928') # 相当于 ret = re.serach('^d+','sdadsa172节食加胡斐928') # print(ret) # <re.Match object; span=(0, 3), match='172'> # print(ret.group()) # 172 # 2. 替换方法 # 字符串处理的扩展: 切割 替换 # split() # s = 'alex|taibai|egon|' # print(s.split('|')) # ['alex', 'taibai', 'egon', ''] #
# split(pattern, string, maxsplit=0, flags=0) #
s = 'alex83taibai40egon25' # ret = re.split('d+',s) # print(ret) # ['alex', 'taibai', 'egon', ''] # sub(pattern, repl, string, count=0, flags=0) # 谁 新的 原内容 替换次数 # ret = re.sub('d+','H','alex83taibai40egon25',1) # print(ret) # alexHtaibai40egon25 # subn(pattern, repl, string, count=0, flags=0) 返回一个元组,第二个元素是替换的次数 # ret = re.subn('d+','H','alex83taibai40egon25') # print(ret) # ('alexHtaibaiHegonH', 3)

2. re模块的进阶

# re模块的进阶:  时间/空间

# compile  节省你使用正则表达式解决问题的时间
# 编译 正则表达式 编译成字节码, 在多次使用的过程中 不会多次编译(一次编译,多次使用)
# ret = re.compile("d+")  # 已经完成编译了,存在内存.
# print(ret)
# res = ret.findall('alex83taibai40egon25')
# print(res)
# res = ret.search('sdadsa172节食加胡斐928')
# print(res.group())

# finditer  节省你使用正则表达式解决问题的空间/内存(利用迭代器)
# ret = re.finditer('d+','alex83taibai40egon25')
# print(ret)  # ret是迭代器,打印出来是:<callable_iterator object at 0x000001D5128B5320>
# for i in ret:
#     print(i.group())

3. 基础方法总结

# findall  返回列表,找所有的匹配项(从大段的内容中找到匹配的项目)
# search  如果匹配就返回一个变量,通过group取值匹配到的第一个值,不匹配就返回None,group会报错(表单验证)
# match  相当于search的正则表达式中加了一个'^'

# spilt  返回列表,按照这正则规则切割,默认匹配到的内容就会被切掉
# sub/subn  替换,按照正则规则去寻找要被替换的内容,subn返回元组,第二个值是替换的次数

# compile  编译一个正则表达式,用这个结果去search match findall finditer 能够节省时间
# finditer  返回一个迭代器,所有的结果都在这个迭代器中,需要通过循环+group的形式取值 能够节省空间/内存

# 程序的优化(3点):
#       1.简化人的操作(更少的代码做更多的事)
#       2.节省时间
#       3.节省空间/内存

 4. 关于分组(使用分组的两种情况)

1. 对于正则表达式来说,有些时候我们需要进行分组,来整体的约束某一组字符出现的次数
        (.[w]+)?

2. 对于python语言来说,分组可以帮助你更好更精准的找到你真正需要的内容
        <(w+)>(w+)</(w+)>
        (1) search-->分组索引
        (2) findall-->分组优先显示
        (3) 取消findall中的分组优先显示效果
     (4) spilt-->分组显示切割符

        import re
        s = '<a>wahaha</a>'  # 标签语言 html 网页
    (1) 分组在search中的用法:取分组中的内容(索引从1开始)
        ret = re.search('<(w+)>(w+)</(w+)>', s)
        # 所有的结果(不写参数或者写0)
        print(ret.group())  # <a>wahaha</a>
    
        # 数字参数代表的是对应分组中的内容(表示索引:索引从1开始)
        print(ret.group(1))  # a
        print(ret.group(2))  # wahaha
        print(ret.group(3))  # a

       用法: 在search中分组可以被索引,索引从1开始,索引0表示匹配的全部结果,索引数字几,就表示匹配到第几个分组中的内容

    (2) 分组在findall中的用法:也可以取分组中的内容(优先显示)
        ret = re.findall('(w+)', s)
        print(ret)  # ['a', 'wahaha', 'a']
    
        ret = re.findall('>(w+)<', s)
        print(ret)  # ['wahaha']    这里优先显示分组中的内容

        用法: 在findall中的分组表示优先显示分组中的内容,可以使一个可以是多个.

    (3) 用?:取消findall中的分组优先  语法:(?:正则表达式)   
      如果我们在正则中已经用分组(括号)来约束了某一组字符出现的次数,这时拿到    python中的re模块findall方法中来用, 打印出来的和你想要的结果不一样, 原因是优先显示了分组中的内容. 
      那么我们如何在findall中取消分组的优先显示的效果呢?
    
      # 取消分组优先(?:正则表达式) 只用于findall
      # 取消优先之前
      ret = re.findall('d+(.d+)?', '1.234*4.3')
      print(ret)  # ['.234', '.3']
    
      # 用?:取消分组优先之后
      ret = re.findall('d+(?:.d+)?', '1.234*4.3')
      print(ret)  # ['1.234', '4.3']

    (4) 分组在spilt中显示切割符(类似于优先显示)
        # 普通显示只显示切割后的结果
        ret = re.split('d+', 'alex83taibai40egon25')
        print(ret)  # ['alex', 'taibai', 'egon', '']

        # 用分组后也显示分隔符
        ret = re.split('(d+)', 'alex83taibai40egon25')
        print(ret)  # ['alex', '83', 'taibai', '40', 'egon', '25', '']

5. 分组命名及使用

1. 分组命名 (?P<名字>)正则表达式
    s = '<a>wahaha</a>'
    ret = re.search('>(?P<con>w+)<', s)
    print(ret.group(1))  # wahaha
    print(ret.group('con'))  # wahaha

2. 使用
    在我们做爬虫时, 会拿到许多标签.如果我只想要某一个标签,怎么办?

    比如: 我想得到<a>..</a>这个标签里的内容
    # 方法1(判断是否相等)
    s = '<a>wahaha</a> <b>dasdfa<b>'
    pattern = '<(w+)>(w+)</(w+)>'
    ret = re.search(pattern, s)
    if ret.group(1) == ret.group(3):
        print(ret.group())  # <a>wahaha</a>

    # 方法2(用分组命名)
    # 使用前面的分组,要求使用这个名字的分组和前面同名分组中的内容匹配的必须一致
    pattern = '<(?P<tab>w+)>(w+)</(?P=tab)>'
    ret = re.search(pattern, s)
    print(ret.group())  # <a>wahaha</a>
原文地址:https://www.cnblogs.com/kangqi452/p/11380895.html