Python高级 -- 04 正则表达式

一、正则表达式


1、匹配单个字符




正则表达式Demo


# 使用正则表达式导入re模块
import re

"""
    使用match(regx, str) 进行正则表达式的匹配
            regx :正则表达式字符串
            str : 要进行匹配的字符串
            如果匹配成功,有返回值,匹配失败,返回值是None
"""


"""  \d : 表示匹配单个数字  """
ret1 = re.match(r"速度与激情\d", "速度与激情1")
print(ret1)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情1'>

ret2 = re.match(r"速度与激情\d", "速度与激情a")
print(ret2)     # None



"""  [] : 表示匹配[]中列举的字符  """
# [1-9] : 表示匹配 1~9 之间的任意一个数字
ret3 = re.match(r"速度与激情[1-9]", "速度与激情1")
print(ret3)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情1'>

# [1-46-8] : 表示匹配 1~4 6~8 之间的的任意一个数字
ret4 = re.match(r"速度与激情[1-4,6-8]", "速度与激情5")
print(ret4)     # None

# [a-zA-z0-9] : 表示匹配a~z A~Z 0~9 的任意字符
ret5 = re.match(r"速度与激情[a-zA-z0-9]", "速度与激情5")
print(ret5)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情5'>



"""  \w  : 表示匹配任意一个字母、数字、_等(包括所有的汉字,只要是一个字符就可以) """
ret6 = re.match(r"速度与激情\w", "速度与激情时")
print(ret6)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情时'>


"""  \s : 表示匹配一个空格或者一个Tab键  """
ret7 = re.match(r"速度与激情\s", "速度与激情 ")
print(ret7)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情 '>

ret8 = re.match(r"速度与激情\s", "速度与激情   ")
print(ret8)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情 '>


"""  . : 表示匹配任意单个字符,包括! # 等,但是不能表示换行符\n  """
ret9 = re.match(r"速度与激情.", "速度与激情!")
print(ret9)     # <_sre.SRE_Match object; span=(0, 6), match='速度与激情!'>

ret10 = re.match(r"速度与激情.", "速度与激情#")
print(ret10)    # <_sre.SRE_Match object; span=(0, 6), match='速度与激情#'>

2、匹配多个字符




正则表达式Demo


import re

"""  \d{1,3} : 表示匹配1个到匹配3个数字之间的任意条件,1个数字可以,2个数字可以,3个数字也可以  """
ret = re.match(r"速度与激情\d{1,8}", "速度与激情4")
print(ret)      # <_sre.SRE_Match object; span=(0, 6), match='速度与激情4'>


"""  \d{11} : 表示匹配的数字个数只能是11  """
ret2 = re.match(r"手机号:\d{11}", "手机号:12345678899")
print(ret2)     # <_sre.SRE_Match object; span=(0, 15), match='手机号:12345678899'>

ret3 = re.match(r"QQ号:\d{5}", "QQ号:1234")
print(ret3)     # None


"""  -? : 表示?号前面的字符可有可无  """
ret4 = re.match(r"北京电话:010-?\d{8}", "北京电话:010-12345678")
ret5 = re.match(r"北京电话:010-?\d{8}", "北京电话:01012345678")
print(ret4)     # <_sre.SRE_Match object; span=(0, 17), match='北京电话:010-12345678'>
print(ret5)     # <_sre.SRE_Match object; span=(0, 16), match='北京电话:01012345678'>


"""  * : 表示0个或者多个  """
ret6 = re.match(r".*", "s")
ret7 = re.match(r".*", "")
print(ret6)     # <_sre.SRE_Match object; span=(0, 1), match='s'>
print(ret7)     # <_sre.SRE_Match object; span=(0, 0), match=''>


"""  + :表示至少出现一次  """
ret8 = re.match(r".+", "sss")
ret9 = re.match(r".+", "")
print(ret8)     # <_sre.SRE_Match object; span=(0, 3), match='sss'>
print(ret9)     # None




3、匹配开头结尾




正则表达式Demo


"""
    判断列表中的变量名是否符合标识符的命名规范
"""
import re


def main():
    list1 = ["0name", "!name", "_name", "$name", "aName", "Name", "name_", "nam_e", "name#", "name!", "name2", "name$"]

    for name in list1:
        """  ^\d : 表示必须以数字开头   """
        """  \d$ : 表示必须以数字结尾   """
        ret = re.match(r"^[a-zA-z_][a-zA-Z0-9_]*$", name)    # match方法默认包含从头匹配
        if ret:
            print("变量名: %s 符合定义要求, 使用正则匹配出来的结果是:%s" % (name, str(ret.group())))
        else:
            print("变量名: %s 不符合定义要求。" % name)


if __name__ == "__main__":
    main()

"""
    结果:
        变量名: 0name 不符合定义要求。
        变量名: !name 不符合定义要求。
        变量名: _name 符合定义要求, 使用正则匹配出来的结果是:_name
        变量名: $name 不符合定义要求。
        变量名: aName 符合定义要求, 使用正则匹配出来的结果是:aName
        变量名: Name 符合定义要求, 使用正则匹配出来的结果是:Name
        变量名: name_ 符合定义要求, 使用正则匹配出来的结果是:name_
        变量名: nam_e 符合定义要求, 使用正则匹配出来的结果是:nam_e
        变量名: name# 不符合定义要求。
        变量名: name! 不符合定义要求。
        变量名: name2 符合定义要求, 使用正则匹配出来的结果是:name2
        变量名: name$ 不符合定义要求。
"""


4、匹配分组




正则表达式Demo


(1)、验证邮箱


import re


def main():
    mail = input("请输入您的邮箱(5-20位):")
    """
        如果在正则表达式中需要用到某些在正则表达式中代表特殊含义的字符,如:+ . ? 等,需要转义 \.  \+  \?
    """
    ret = re.match(r"[a-zA-Z0-9]{5,20}@(163|126|itcast|efunbox)\.com$", mail)
    if ret:
        print("%s 邮箱符合要求" % mail)
    else:
        print("%s 邮箱不符合要求" % mail)


if __name__ == "__main__":
    main()


(2)、正则模拟实现html标签匹配


import re


"""
    模拟实现html标签匹配
"""
# (reg) : 用()括起来表示一个分组,分组顺序从左至右由 1 开始,依次增加
# \1 : 表示使用第一个分组中的正则表达式
ret = re.match(r"<(\w*)>.*</\1>", "<h1>aaa</h1>")
print(ret)      # <_sre.SRE_Match object; span=(0, 12), match='<h1>aaa</h1>'>
# 从匹配的字符串中获取第一个分组中的数据
print(ret.group(1))     # h1


ret2 = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", "<tr><td>你好</td></tr>")
print(ret2.group(1))        # tr
print(ret2.group(2))        # td


5、re模块的高级用法


(1)、search方法


import re


"""
    search() : 该方法表示匹配字符串中的第一个满足正则表达式的值
"""
ret = re.search("\d+", "文章的阅读数为:89999")
print(ret)          # <_sre.SRE_Match object; span=(8, 13), match='89999'>
print(ret.group())  # 89999


(2)、findall


import re


"""
    findall() : 该方法表示匹配所有满足正则表达式的值,并返回一个列表
"""
ret2 = re.findall("\d+", "java=9999, python=8888, c=7777, c#=6666")
print(type(ret2))       # <class 'list'>
print(ret2)             # ['9999', '8888', '7777', '6666']


(3)、sub


import re


"""
    sub(regex, value, str) 替换字符串中匹配到的正则数据, 返回替换完成之后的字符串, 源字符串保持不变
        regex : 正则表达式
        value : 将字符串中匹配到正则表达式的数据替换为的值(此处可以放一个函数的引用,即可以调用函数)
        str   : 字符串
"""
str1 = "java=9999, python=8888, c=7777, c#=6666"
ret2 = re.sub("\d+", "1000", str1)
print(type(ret2))       # <class 'str'>
print(ret2)             # java=1000, python=1000, c=1000, c#=1000
print(str1)              # java=9999, python=8888, c=7777, c#=6666


""" value 写成函数调用的方式, 要求:函数必须是有返回值的, 且返回值必须是字符串类型 """
def add(temp):  # 参数temp就是正则表达式匹配成功之后的对象
    a = 100 + 200
    return str(a)

str2 = "java=9999, python=8888, c=7777, c#=6666"
ret3 = re.sub("\d+", add, str2)
print(ret3)     # java=300, python=300, c=300, c#=300


(4)、split


import re


"""
    split(regex, str) : 将字符串按照正则表达式进行切割,并返回一个列表
"""
ret = re.split(r"\d+", "java=00, c++=01, python=02")
print(type(ret))        # <class 'list'>
print(ret)              # ['java=', ', c++=', ', python=', '']


(5)、案例:对html中的标签进行过滤


import re


"""
    案例:清洗html标签
"""
html = """
        <dd class="job_bt">
            <h3 class="description">职位描述:</h3>
            <div>
                <p class="job-title">职位描述:</p>
                <p>
                    1.公司核心产品开发, 优化, 维护,可以独立开发相关业务模块;
                    <br>2.以敏捷开发模式,快速迭代,集成第三方webservice等接口;
                    <br>3.结合产品目标进行技术创新。
                    <br>职位要求:
                    <br>1.本科或以上学历, 计算机软件相关专业优先;
                    <br>2.连续2年以上以Python为主的中型或大型互联网产品开发及维护工作经验;
                    <br>3.熟悉MySQL数据库, 拥有优秀的数据库设计能力, 对数据库的基本理论及其内部实现机制有比较深刻的理解;
                    <br>4.熟悉git的使用,能在linux环境下开发,布署;
                    <br>5.完善并遵守团队的编码规范, 编写高质量、结构清晰、易读、易维护的代码;
                    <br>6.善于沟通和逻辑表达,良好的团队合作精神和积极主动的沟通意识。
                </p>
            </div>
        </dd>
    """

ret = re.sub(r"<[^>]*>|\s+| ", "", html)
"""  正则表达式中的[^>] 表示匹配的字符只要不是^>就可以 ⭐⭐⭐ """
print(ret)

"""
    运行结果:
        职位描述:职位描述:1.公司核心产品开发,优化,维护,可以独立开发相关业务模块;
        2.以敏捷开发模式,快速迭代,集成第三方webservice等接口;3.结合产品目标进行技术创新。
        职位要求:1.本科或以上学历,计算机软件相关专业优先;2.连续2年以上以Python为主的中型或
        大型互联网产品开发及维护工作经验;3.熟悉MySQL数据库,拥有优秀的数据库设计能力,对数据库
        的基本理论及其内部实现机制有比较深刻的理解;4.熟悉git的使用,能在linux环境下开发,布署;
        5.完善并遵守团队的编码规范,编写高质量、结构清晰、易读、易维护的代码;6.善于沟通和逻辑表达,
        良好的团队合作精神和积极主动的沟通意识。
"""



6、贪婪和非贪婪


import re


"""
    python中的正则表达式默认是贪婪的,即:条件成立的情况下,正则表达式会趋向于匹配更多的数据
        +       :   表示一个或者多个,默认贪婪,如果表达式成立,就会匹配多个 
        *       :   表示没有或者有或者很多个,默认贪婪,就会匹配多个
        ?       :   表示又或者没有,默认贪婪,就会匹配有数据的
        {m, n}  :   表示至少m个,最多n个,默认贪婪,会匹配n个
        
    解决python的贪婪性 :在表达式后面加上 ? 号,强制改编为非贪婪,非贪婪即取最少的匹配结果
        +?      :   有多个匹配结果时,只匹配一个   
        *?      :   有多个匹配结果时,选择匹配0个
        ??      :   选择匹配没有
        {m, n}? :   选择匹配最少的m
"""

str1 = "a;sldgasogi 012-664-32-26-85"
ret1 = re.match(r".*(\d+-\d+-\d+-\d+-\d+)", str1)
print(ret1.group(1))        # 2-664-32-26-85
"""  以上结果为:2-664-32-26-85  因为.*是贪婪的,在下一个正则表达式匹配到数据之前,所有能匹配的数据都被.*匹配走了  """

ret2 = re.match(r".*?(\d+-\d+-\d+-\d+-\d+)", str1)
print(ret2.group(1))        # 012-664-32-26-85


7、案例:使用正则表达式下载图片


import re
import gevent
import urllib.request
from gevent import monkey


"""
   使用正则表达式将斗鱼网站的页面图片全部下载到本地。
        操作步骤:
            1.选择一个页面,将页面源代码粘贴到文本文档中
            2.使用文件流读取文件内容
            3.使用正则表达式获取所有的图片链接
            4.使用gevent多任务下载图片
"""


def read_html(html_name):
    f = open(html_name, "r", encoding="utf-8")
    content = f.read()
    return content


def get_img_list(html_content):
    regex = r"https://.*?\.jpg"
    html_list = re.findall(regex, html_content)
    return html_list


# 打延时补丁
monkey.patch_all()


def download_img(img_url, img_name):
    req = urllib.request.urlopen(img_url)

    img_content = req.read()

    with open(img_name, "wb") as f:
        f.write(img_content)


def main():

    # 获取要爬的html文件名称
    html_name = input("请输入要爬取的html文件名称:")
    # 调用函数,读取文件内容,放到html字符串中
    html_content = read_html(html_name)
    # 调用函数,匹配出所有的图片链接
    img_list = get_img_list(html_content)
    # 调用函数,下载所有的图片
    i = 0
    for img_url in img_list:
        g = gevent.spawn(download_img, img_url, "%d_girl.jpg" % i)
        i += 1
        g.join()


if __name__ == "__main__":
    main()




8、r的作用


import re

"""
    正则表达式前面的 r 表示对正则表达式中的特殊字符,如:\等进行转义
"""

str1 = "c:\\a\\b\\c"
ret1 = re.match("c:\\\\a", str1)    # \\\\a : 第1个第3个 \ 是对第2个第4个 \ 的转义
print(ret1.group())     # c:\a

ret2 = re.match("c:\\a", str1)
print(ret2)             # None
# print(ret2.group())     # 报错,没有匹配到,None调用group方法报错

ret3 = re.match(r"c:\\a", str1)
print(ret3)             # <_sre.SRE_Match object; span=(0, 4), match='c:\\a'>
print(ret3.group())     # c:\a


"""
    以上例子可以看出,加上r之后,就会自动将正则表达式中需要转义的字符进行转义
    即:字符串中怎么写的,加上r以后,正则表达式就可以怎么写⭐⭐⭐
"""


猜你喜欢

转载自blog.csdn.net/wingzhezhe/article/details/79238791