正则表达式知识点总结

正则表达式:


一、正则表达式概述
作用:
1.数据抓取、数据提取,比如:抓取网站中图片地址,该如何描述要获取的数据的规则
2.数据清洗:把不雅的评论清洗掉
3.数据验证:验证手机号码的合法性:11位数字,邮箱:@




二、re模块介绍
1.re模块的使用过程
1.导入模块:import re
2.匹配:ret = re.match("正则表达式","要匹配的字符串")
3.判断匹配是否成功
ret:不为空:表示匹配成功
为空:表示匹配失败
4.取匹配的结果
ret.group()


注意:re.match():匹配以xxx开头的字符串
re.match("itcast","itcast.com.cn")
匹配以itcast开头的字符串


三、匹配单个字符(重点)
1.'.' :表示匹配任意一个字符,除\n(换行)以外
问题:看电影 输入电影名称"速度与激情"时,'激'字符可以任意输入,都算成功
ret = re.match("速度与.情","速度与激情")
ret = re.match("速度与.情","速度与j情")
ret = re.match("速度与.情","速度与即情")
ret = re.match("速度与.情","速度与#情")
ret = re.match("速度与.情","速度与\n情")
2.[]:匹配[]中列举的字符
问题:看电影 输入电影名称时,"速度与激情1"-"速度与激情9"都是正确的
ret = re.match("速度与激情[123456789]","速度与激情1")
ret = re.match("速度与激情[123456789]","速度与激情A")
ret = re.match("速度与激情[1-9]","速度与激情3")
ret = re.match("速度与激情[1-35-9]","速度与激情9")
ret = re.match("速度与激情[1-35-9]","速度与激情4")


3.\d: 匹配数字,即0-9
问题:看电影 输入电影名称时,"速度与激情"后面接的一个字符只要是数字都是正确的


ret = re.match("速度与激情\d","速度与激情A")
ret = re.match("速度与激情\d","速度与激情9")


4.\D: 匹配非数字,即不是数字
ret = re.match("速度与激情\D","速度与激情人")
ret = re.match("速度与激情\D","速度与激情*")
ret = re.match("速度与激情\D","速度与激情9")


5.\s :匹配空白,包含空格和tab键
ret = re.match("速度与激情\s","速度与激情   ")
ret = re.match("速度与激情\s","速度与激情1")

6.\S :匹配非空白
ret = re.match("速度与激情\S","速度与激情1")
ret = re.match("速度与激情\S","速度与激情   ")


7.\w:匹配单词字符,包含(0-9,a-z,A-Z,_)
注意:在python3中,中文字符也包含在单词字符中,而python2不包含
ret = re.match("\w","1")
ret = re.match("\w","_")
ret = re.match("\w","a")
ret = re.match("\w","中")
ret = re.match("\w","@")


8.\W :匹配非单词字符,即非单词字符
ret = re.match("\W","@")
ret = re.match("\W","A")
ret = re.match("\W","中")


四、匹配多个字符(重点)
1.{m} :匹配前一个字符出现m次
问题:请匹配出合法的手机号码
规则:要求满足11位数字,且第一位数是1
ret = re.match("1\d{10}","13664649235")


2.{m,n}:匹配前一个字符出现m到n次
问题:验证电话号码的合法性,比如:010-56745675,0755-12345678,0835-1234567
匹配规则:区号3-4位数字,电话号码是7-8位数字,中间可用'-'连接区号与电话号
ret = re.match("\d{3,4}-\d{7,8}","010-56745675")


3.?:前一个字符穿线1次或者0次,要么出现一次,要么一次都没有
问题:匹配电话号码的合法性,比如02056745675,0755-12345678,07561234567
匹配规则:区号3-4位数字,电话号码是7-8位数字,中间可用'-'连接区号与电话号


4.* :匹配前一个字出现0次或者多次
问题:把一个文本的内容全部取出来
参考文本: content="""adslfjaldjgljagga\nasdiwerierydfgjr\n;sdfgrwjtrjg"""
ret = re.match(".*",content,re.S)


5. +:匹配前一个字符出现1次或者无限次,即至少有1次
问题:起始位置,a字符至少出现一次
ret = re.match("a+","aaaaa")
ret = re.match("a+","a")
ret = re.match("a+","")


五、匹配开头和结尾
1.^:匹配以xxx开头的字符串
ret = re.match("^itcast","itcast.cn")
ret = re.match("^itcast","citcast.cn")
ret = re.match("itcast","itcast.cn")


2.案例2:
匹配出以下合法的163邮箱
email_list = ["[email protected]", "[email protected]", "[email protected]", "[email protected]","cheny@163ccom","[email protected]"]
匹配规则:每个邮箱必须以'@163.com'为后缀,且'@'之前有4-20个单词字符,例如[email protected]




ret = re.match("\w{4,20}@163\.com$", email)
        # . 在正则表达式代表特殊的意义(表示任意一个字符),所以需要还原成原来的本意,在'.' 前面加'\',转为原来的本意
        fx:
import re


if __name__ == '__main__':
    """匹配规则:每个邮箱必须以'@163.com'为后缀,且'@'之前有4-20个单词字符,例如[email protected]"""
    email_list = ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "cheny@163ccom",
                  "[email protected]"]


    for email in email_list:
        ret = re.match("\w{4,20}@163[.]com$", email)


        # . 在正则表达式代表特殊的意义(表示任意一个字符),所有需要还原成原来的本意,在'.' 前面加'\'
        if ret:
            print("变量名%s匹配成功,匹配结果是:%s" % (email, ret.group()))
        else:
            print("变量名%s匹配不成功" % email)




七、匹配分组
1.|:匹配左右任意一个表达式
问题:请写出能同时验证163或者126合法邮箱的正则表达式
匹配规则:每个邮箱必须有@符号,且@符号之前需有4到20位单词字符
ret = re.match("\w{4,20}@163\.com$|\w{4,20}@126\.com$","[email protected]")


2.(ab) :分组


问题1 :请写出能同时验证163或者126合法邮箱的正则表达式
匹配规则:每个邮箱必须有@符号,且@符号之前需有4到20位单词字符
ret = re.match("\w{4,20}@(163|126|qq)\.com$","[email protected]")
问题2:想取出合法邮箱特定的值,比如取163,126,qq或者邮箱的前缀


1.取163、126、qq
1.表示匹配出的结果放在第0组
ret.group()
ret.group(0)
2.ret.group(1):把自己加的()分组进行编号,并且通过ret.group(1)可以取出值


2.取邮箱的前缀(@符号前面的字符串)
ret = re.match("(\w{4,20})@(163|126|qq)\.com$","[email protected]")
ret.group(1)


3.\num :引用分组num匹配到的字符串
问题:检验html网页语法的合法性
语法规则:html双标签必须配对,比如<h1>asda<h1>
1.不严谨的写法
ret = re.match("<\w+>.*</\w+>","<h1>asda</h1>")


2.严谨的写法
ret = re.match("<\w+>.*</\\1>","<h1>asdasd</h1>")
#\\1:表示对\再转义,还原成原来的本意'\'




4.(?P<name>):分组起别名
5.(?P=name):引用别名为name分组匹配到的字符串
问题:检验html网页语法的合法性
语法规则:html双标签必须配对,比如<body><h1></h1></body>
ret=re.match("<(\w+)><(\w+)>.+</\\2></\\1>","<body><h1>dsafagd</h1></body>")


ret=re.match("<(?P<p1>\w+)><(?P<p2>\w+)>.+</(?P=p2)></(?P=p1)>","<body><h1>dsafagd</h1></body>")


八.re模块的高级用法


1.re.search():查找匹配的数据,匹配到则立即返回
语法:re.search("正则表达式","查找的字符串或者文本")
问题:匹配微信公众号文章阅读的次数
文本如下:"本文章阅读次数:9998次,博客的阅读次数:50"


ret = re.search("\d+","本文章阅读次数:9998次,博客的阅读次数:50")




2.re.findall():查找字符串中所有匹配的数据,返回的是列表
语法:re.findall("正则表达式","查找的字符串或者文本")
问题:找到本文的所有数字
文本如下:"本文章阅读次数:9998,博客阅读次数:50"


ret = re.findall('\d+','本文章阅读次数:9998,博客的阅读次数:50')
注意:把所有满足的结果匹配出来
返回结果是list


3.re.sub() :查找与替换,返回的是替换后的字符串
语法:re.sub("正则表达式","替换的内容","查找的字符串或者文本")
问题:将匹配到的数字加1
文本如下:"本文章阅读次数:9998次,博客的阅读次数:50"


ret=re.sub("\d+",'9998',"本文章阅读次数: 9998次,博客的阅读次数: 50")


In [254]: def add(match):                                                   
     ...:     strnum=match.group()
     ...:     num=int(strnum)+1
     ...:     return str(num)


ret=re.sub("\d+",add,"本文章阅读次数: 9998次,博客的阅读次数: 50")  




4.split :按规则分离字符串,返回的是分离后的列表
语法:re.split("分隔符正则表达式","要分割的文本")
问题:分离字符串 "wang 22 北京 python"
ret = re.split("|:","wang 22:北京 python")


In [260]: ret=re.split(" |:","wang 22:北京 python")


In [261]: ret
Out[261]: ['wang', '22', '北京', 'python']


注意: 返回的是列表


九、案例:从下面的拉钩网页源码中获取职位描述信息(数据清洗)


1. ret=re.sub("<\w+>|</\w+>|\s|&nbsp;","",content)
      # \s 能够匹配空白,还有\n 
   2. ret=re.sub("<[^>]+>|\s|&nbsp;","",content)
    注意: '^'假如在[]里面,则表示取反






<div>
        <p>岗位职责:</p> 
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与搜索实验室的模型/算法工程师合作推进深度学习的在360搜索中的实际落地应用<br> 2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;负责搭建搜索实验室在线推理服务及相应运维框架</p>
<p>技术方向及要求:<br> 1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;至少2年以上Python在线系统开发经验, 对在线项目的设计、开发、运维有足够的认识<br> 2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;熟悉LINUX系统开发,扎实的数据结构与算法知识<br> 3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有过K8S/Docker/ElasticSearch 深度使用经验或定制开发经验者优先<br> 4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有C++/golang开发经验者优先<br> 5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有过tensorflow serving/mxnet/caffe 在线服务开发经验者优先</p>
        </div> 




十、贪婪和非贪婪


十、贪婪和非贪婪
1. Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。


2. 在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪


问题:测试"*","?","+","{m,n}变为非贪婪后,匹配字符的个数
把 "*","?","+","{m,n}变为非贪婪,只要在后面加?
*?  0个
?? 0个
+? 1个
{m,n} m个
   
    小案例:抓取斗鱼网中颜值美女图片


    <img alt="米米nnn的直播" data-original="https://rpic.douyucdn.cn/live-cover/appCovers/2018/04/25/2228580_20180425203852_big.jpg" src="https://shark.douyucdn.cn/app/douyu/res/page/list-item-def-rect-thumb.jpg" width="283" height="163" class="JS_listthumb">
                                        <div class="live-device-wrap device-mobile">




十一、r的作用
   Python中字符串前面加上 r 表示原生字符串
   大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰
   Python里的原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
   path="c:\\a\\b\\c"
   ret=re.match("c:\\\\",path)
   前面加r,把\变为原生的意义,就是反斜杠
   ret=re.match(r"c:\\",path)


   ret=re.match(r"<(\w+)><(\w+)>.+</\2></\1>","<body><h1>dsafagd</h1></body>")

猜你喜欢

转载自blog.csdn.net/owc1874/article/details/80502958