zoukankan      html  css  js  c++  java
  • re模块

    一、re模块

           首先说一下什么是模块,模块就是一组功能的集合。你要和某个东西打交道,而这个东西本身和python没关系,这个东西本身就存在,所以python提供了一个功能的集合专门负责和这个东西打交道。

           模块的类型:

                  内置模块:不需要我们自己安装,解释器自带的;

                  第三方模块:需要我们自己安装的模块;

                  自定义模块:我们自己写的模块;

           为什么要有模块?先举一个例子:我们都知道是操作系统把所有硬件管理起来的,文件是在硬盘上存储的,python想从硬盘上进行文件的操作和删除时就需要引入os模块,说白了,模块实际上就是给我们提供功能,这个要操作的内容本身就存在,模块只不过是python提供给我们去操作这个内容的方法。

           注意:永远不要起一个和你已知的模块同名的py文件的名字!

           今天我们就来学习一下re模块的几个基础方法,在python中使用正则表达式就要引入re模块。

    1,查找

      findall:表示匹配每一项都是列表中的一个元素。 (重要程度*****)(可用于从大段内容中找到匹配的项目)

           语法规则:re.findall(‘正则表达式’, 待匹配字符串 , flag),具体示例如下:

        import re
        ret = re.findall('d+', 'sjkhk172按实际花费928')
        print(ret)  # 结果为:['172', '928']
            
        ret = re.findall('d', 'sjkhk172按实际花费928')
        print(ret)  # 结果为:['1', '7', '2', '9', '2', '8']

      search:只匹配从左到右的第一个,得到的不是直接的结果,而是一个变量,通过这个变量的group方法来获取结果,如果没有匹配到,会返回None,使用group会报错。(重要程度*****)(可用于表单验证)

           语法规则:re.search(‘正则表达式’, 待匹配字符串 , flag),具体示例如下:

        ret = re.search('d+', 'sjkhk172按实际花费928')
        print(ret)  # 结果为:<_sre.SRE_Match object; span=(5, 8),     match='172'>
        print(ret.group()) # 结果为:172
    
        ret = re.search('d','owghabDJLBNdgv')
        print(ret)   # 结果为:None
        print(ret.group())   # 会报错
    
        # 因为search方法查找的时候,若待匹配的字符串中没有能匹配到的结果时,
        # 用group会报错,所以通常我们写成下面这样
        ret = re.search('d+','sjkhk172按实际花费928')
        if ret :   # 内存地址,这是一个正则匹配的结果
            print(ret.group()) # 通过ret.group()获取真正的结果

      match:从头开始匹配,相当于search中的正则表达式加上一个^。(重要程度**)

           语法规则:re.match(‘正则表达式’, 待匹配字符串 , flag),具体示例如下:

        ret = re.match('d+$','sjkhk172按实际花费928')
        print(ret)  # 结果为:None
        ret = re.match('d+','172sjkhk按实际花费928')
        print(ret)  # 结果为:<_sre.SRE_Match object; span=(0, 3),     match='172'>
        print(ret.group())  # 结果为:172
        ret = re.match('d+$','172sjkhk按实际花费928')
        print(ret)  # 结果为:None
    2,字符串处理的扩展

           切割:re.split(‘正则表达式’, 待匹配字符串),用正则表达式匹配出来的结果对待匹配字符串切割。如下:

        s = 'alex83taibai40egon25'
        ret = re.split('d+',s)
        print(ret)  # 结果为:['alex', 'taibai', 'egon', '']

      替换:sub和subn

                  re.sub(‘正则表达式’, ‘新内容’, 待匹配字符串 , 替换次数)

        re.subn(‘正则表达式’, ‘新内容’, 待匹配字符串 , 替换次数) ,示例如下:

        ret = re.sub('d+','H','alex83taibai40egon25')
        print(ret)  # 结果为:alexHtaibaiHegonH
        ret = re.sub('d+','H','alex83taibai40egon25',1)
        print(ret)  # 结果为:alexHtaibai40egon25
    
        ret = re.subn('d+','H','alex83taibai40egon25')
        print(ret)  # 结果为:('alexHtaibaiHegonH', 3)
        ret = re.subn('d+','H','alex83taibai40egon25', 2)
        print(ret)  # 结果为:('alexHtaibaiHegonH', 2)
        # 我们可以看出sub和subn的区别是subn返回一个元组,元组第二个元素是替换次数。
    3,re模块的进阶:时间和空间上更优化

           compile:节省使用正则表达式解决问题的时间(编译,就是将正则表达式编译成字节码,这样在多次使用的过程中不会多次编译,可以用这个结果去直接search、match、findall、finditer),具体示例如下:

        ret = re.compile('d+')   # 编译
        print(ret)  # 结果为:re.compile('\d+')
        res = ret.findall('alex83taibai40egon25')  # 编译后直接使用
        print(res)
        res = ret.search('sjkhk172按实际花费928')  # 编译后直接使用
        print(res.group())

      finditer:节省使用正则表达式解决问题的空间/内存(返回一个迭代器,所有的结果都在这个迭代器中,可以通过循环和group取出来),具体示例如下:

        ret = re.finditer('d+','alex83taibai40egon25')
        print(ret)  # 结果为:<callable_iterator object at 0x00000000029EFDA0>
        for i in ret:
            print(i.group())
        # 结果为:
        # 83
        # 40
        # 25

    二、在python中使用正则表达式的特点和问题

    1,分组在re模块中的使用

      分析如下几段代码,理解并总结规则:

        # 1 search方法中对正则分组,通过group(n)取出相应内容
        s = '<a>wahaha</a>'
        ret = re.search('<(w+)>(w+)</(w+)>',s)
        print(ret.group())  # 结果为:<a>wahaha</a>,默认取出所有匹配内容
        print(ret.group(1)) # 数字参数代表的是取对应分组中的内容,结果为:a
        print(ret.group(2))  # 结果为:wahaha
        print(ret.group(3))  # 结果为:a
    
        # 2 findall也可以顺利取到分组中的内容,因为它有一个特殊的语法,就是优先显示分组中的内容
        ret = re.findall('(w+)',s)
        print(ret)  # 结果为:['a', 'wahaha', 'a']
        ret = re.findall('>(w+)<',s)
        print(ret)  # 结果为:['wahaha']
    
        # 3 取消分组优先(?:正则表达式)
        ret = re.findall('>(?:w+)<',s)
        print(ret)  # 结果为:['>wahaha<']
        ret = re.findall('d+(?:.d+)?','1.234*4')
        print(ret)   # 结果为:['1.234', '4']
        # 当你想用()表示正则里的分组,而不想表示优先显示的时候可以用?:取消分组

      综上: 对于正则表达式来说,有些时候我们需要进行分组,来整体约束某一组字符出现的次数;对于python语言来说,分组可以帮助你更好更精准的找到你真正需要的内容;具体想表示哪种分组,要看情况决定。

        # 4 split方法中可以对正则加括号表示使切割的字符不丢失
        ret = re.split('d+','alex83taibai40egon25')
        print(ret)  # 结果为:['alex', 'taibai', 'egon', '']
        ret = re.split('(d+)','alex83taibai40egon25')
        print(ret)  # 结果为:['alex', '83', 'taibai', '40', 'egon', '25', '']
    
        # 分组命名 (?P<组名>正则表达式)
        s = '<a>wahaha</a>'
        ret = re.search('>(?P<con>w+)<',s)
        print(ret.group(1))  # 结果为:wahaha
        print(ret.group('con'))  # 结果为:wahaha
    
        # 使用前面的分组 要求使用这个名字的分组和前面同名分组中的内容匹配的必须一致
        pattern = '<(?P<tab>w+)>(w+)</(?P=tab)>'
        ret = re.search(pattern,s)
        print(ret.group())   # 结果为:<a>wahaha</a>
        # 可以练习下列的匹配:
        # 2018-12-06
        # 2018.12.6
        # 2018 12 06
        # 12:30:30

    三、使用正则表达式的技巧

           当你要匹配的内容太没有特点,容易和你不想匹配的内容混在一起的时候,就可以把不想匹配的也取出来,然后通过python过滤掉,具体示例如下:

        # 想只取整数,但是会带上小数,那么把整数和小数都取出来,然后再过滤掉小数
        ret=re.findall(r"d+.d+|d+","1-2*(60+(-40.35/5)-(-4*3))")
        print(ret)  # 结果为:['1', '2', '60', '40.35', '5', '4', '3']
        ret=re.findall(r"d+.d+|(d+)","1-2*(60+(-40.35/5)-(-4*3))")
        ret.remove('')
        print(ret)  # 结果为:['1', '2', '60', '5', '4', '3']

    四、爬虫的例子

           预备知识:如何获取一个页面的源代码,如下可以做到:

        from urllib import request
        ret = request.urlopen('https://movie.douban.com/top250?start=50&filter=')
        res = ret.read().decode('utf-8')
        print(res)

      分析并掌握如下爬虫的小例子:

        import re
        from urllib.request import urlopen
    
        def getPage(url):   # 获取网页的字符串
            response = urlopen(url)
            return response.read().decode('utf-8')
    
        def parsePage(s):
            ret = com.finditer(s)  # 从s这个网页源码中 找到所有符合com正则表达式规则的内容 并且以迭代器的形式返回
            for i in ret:
                yield {
                    "id": i.group("id"),
                    "title": i.group("title"),
                    "rating_num": i.group("rating_num"),
                    "comment_num": i.group("comment_num"),
                }
    
        def main(num):  # 0  25 50  # 这个函数执行10次,每次爬取一页的内容
            url = 'https://movie.douban.com/top250?start=%s&filter=' % num
            response_html = getPage(url)   # response_html就是这个url对应的html代码 就是 str
            ret = parsePage(response_html) # ret是一个生成器
            print(ret)
            f = open("move_info7", "a", encoding="utf8")
            for obj in ret:
                print(obj)
                data = str(obj)
                f.write(data + "
    ")
            f.close()
    
        com = re.compile(
            '<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>', re.S)
         # 这里re.S表示正则表达式中的.不只匹配非换行符,还匹配换行符,即匹配任意字符 count
    = 0 for i in range(10): main(count) count += 25

    写在最后:

      正则表达式到底重要到什么程度?

      掌握作业中的所有内容

      能够看懂常用的正则表达式

      并且能够做出一些公司特异性要求的修改

  • 相关阅读:
    现在转战c++的领域,纯幼儿园
    LeetCode:Majority Element
    LeetCode:Partition List
    LeetCode:Balanced Binary Tree(判断是否为二叉平衡树)
    LeetCode:Binary Tree Zigzag Level Order Traversal
    LeetCode:Binary Tree Level Order Traversal II (按层遍历)
    LeetCode:Binary Tree Postorder Traversal(二叉树的后序遍历)
    LeetCode:BInary Tree Inorder Traversal(二叉树的中序遍历)
    LeetCode:Binary Tree Preorder Traversal(二叉树的先序遍历)
    LeetCode:Implement Queue using Stacks
  • 原文地址:https://www.cnblogs.com/li-li/p/9494832.html
Copyright © 2011-2022 走看看