Python字符串过滤器:正则表达式Regular Expression
一、什么是正则表达式
正则表达式是按照正确的既定规则、一种全语言类型Python、Java、JavaScript、PHP通用的表达式。
用途:
(1)根据规则抓取数据:配合爬虫、根据规则在文本中提取数据
(2)根据规则验证数据:验证手机号、验证邮箱、验证身份证
二、如何在Python中使用正则表达式
在Python中正则表达式的1个模块+2个方法需要学习
re模块 re=regular expression
1 | import re |
re方法一:根据规则查找/提取内容
1 | re.findall(查找规则,匹配内容) |
返回结构化数据,两个参数,形式参数为pattern(规律)string(需要查找/匹配的字符串)
re方法二:根据规则匹配/验证内容
1 | re.match(匹配规则,匹配内容) |
返回布尔,两个参数,形式参数为pattern(规律)string(验证字符串)
三、正则表达式的规则
正则表达式普通字符:
(1)普通字符是我们常规认识的a-z A-Z 0-9中文以及标点符号
正则表达式特殊符号/通配符/元字符,常用特殊字符包含:
(1)直接规则字符:. + * ? \d \D \w \W \s \S ^
(2)辅助规则字符(){} []
这几个括弧不是数据类型
字符代表含义
. | 匹配除了换行以外的任何一个字符 |
+ | 匹配前边子表达式规则字符任意次数(至少出现一次) |
* | 匹配前边子表达式规则字符任意次数包含0次 |
? | 尽可能少匹配,禁止贪婪模式 |
\d | 匹配一个数字 |
\D | 匹配一个非数字 |
\w | 匹配包括下划线的任何单词字符 |
\W | 匹配任何非单词字符 |
\s | 匹配任何空白字符 |
\S | 匹配任何非空白字符 |
^ | 字符串开头匹配 |
$ | 字符串结束匹配 |
[] | 筛选条件 |
\b | 代表单词的开始或者结束(以标点、空格、换行作为分割) |
\B | 匹配不位于单词开始或结束位置的空字符串 |
() | 分组(作为一个整体) |
{m,n} | 匹配前一个元字符m到n次 |
\\ | 转移字符,跟在其后的字符将失去作为特殊元字符的含义 |
特别注意^符号与[]搭配使用代表"非" 如[^a],非a全取
举例:任务提起老师的姓名
1 2 3 4 5 6 7 8 | import re txt = '''万门大学老师:宁夫 万门大学老师:正正 万门大学老师:陪陪''' pattern = r ":.*" res = re.findall(pattern,txt) print (res) |
输出结果:
1 2 3 4 5 6 7 8 | import re txt = '''万门大学老师:宁夫 万门大学老师:正正 万门大学老师:陪陪''' pattern = r ":(.*)" res = re.findall(pattern,txt) print (res) |
输出结果:
举例:匹配日期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import re pattern = re. compile (r "\d{4}年\d{2}月\d{2}日" ) years = ''' 1900-02-10 1990-03-29 1991-03-31 1901年02月10日 1991年03月29日 1992年03月31日 ''' result = re.findall(pattern, years) print (result) |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import re pattern = re. compile (r "\d{4}[年-]\d{2}[月-]\d{2}" ) years = ''' 1900-02-10 1990-03-29 1991-03-31 1901年02月10日 1991年03月29日 1992年03月31日 ''' result = re.findall(pattern, years) print (result) |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | info = "姓名:boddy 生日:1987年10月1日 本科:2005年9月1日" #match方法是从字符串最开始匹配 #贪婪匹配 match_result1 = re.match( ".*生日.*\d{4}" ,info) print (match_result1.group()) #非贪婪匹配 match_result2 = re.match( ".*生日.*?\d{4}" ,info) print (match_result2.group()) match_result3 = re.match( ".*生日.*?(\d{4}).*本科.*?(\d{4})" ,info) print (match_result3.group( 1 )) print (match_result3.group( 2 )) match_result4 = re.sub( "\d{4}" , "2019" ,info) print (info) print (match_result4) match_result5 = re.search( "生日.*?(\d{4}).*本科.*?(\d{4})" ,info) print (match_result5.group( 1 )) print (match_result5.group( 2 )) |
输出结果:
re匹配模式IGNORECASE 忽略大小写,DOTALL忽略回车换行符
1 2 3 4 5 | name1 = "my name is Bobby" print (re.search( "bobby" , name1,re.IGNORECASE).group()) name2 = '''my name is ' bobby''' print (re.match( ".*bobby" , name2,re.DOTALL).group()) |
输出结果:
举例:提取电话号码
1 2 3 4 5 6 7 8 9 10 | import re info = '''mike,18391911111,39 lin,13932111111,40 danial,15932431115,45 frank,1A932431115,45''' pattern = r "\d{11}" result = re.findall(pattern,info) print (result) |
输出结果:
这里的\d{11}表示的是连续11个数字字符
举例:验证qq邮箱是否合法
1 2 3 4 5 6 | import re qq = "78929302@qq.com" pattern = r "[1-9][0-9]{4,10}@qq.com" result = re.match(pattern,qq) print (( bool (result))) |
QQ号第一位1-9数字,第二位为0-9数字且连续出现4-10次,后面@qq普通字符直接匹配
输出结果:
举例:最基础的普通字符正则表达式
1 2 3 4 5 6 | import re txt = "万门大学" pattern = r "万门" result = re.findall(pattern,txt) print (result) |
输出结果:
举例:通配.遇到一个通配一个
1 2 3 4 5 6 | import re txt = "万门大学" pattern = r "." result = re.findall(pattern,txt) print (result) |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 | import re txt = """ 我在万门学Python 我在万门学java 我在万门学Django 我在万门学PPT """ pattern = re. compile (r "学." ) #compile编译的意思,编译当前的表达式 result = pattern.findall(txt) print (result) |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 | import re txt = """ 我在万门学Python 我在万门学java 我在万门学Django 我在万门学PPT """ pattern = re. compile (r "学.*" ) #compile编译的意思,编译当前的表达式 result = pattern.findall(txt) print (result) |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 | import re txt = """ 我在万门学Python 我在万门学java 我在万门学Django 我在万门学PPT """ pattern = re. compile (r "学.+" ) #compile编译的意思,编译当前的表达式 result = pattern.findall(txt) print (result) |
输出结果:
+号是需要满足至少出现一个才会生效表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import re txt = """ 我在万门学Python 我在万门学java 我在万门学Django 我在万门学PPT 我在万门学 """ pattern1 = re. compile (r "学.+" ) #compile编译的意思,编译当前的表达式 result1 = pattern1.findall(txt) print (result1) pattern2 = re. compile (r "学.*" ) #compile编译的意思,编译当前的表达式 result2 = pattern2.findall(txt) print (result2) |
输出结果:
举例:{}匹配指定次数{3}指定3次{2,5}指定2-5次范围。()数据分组。^从头取值。$从尾巴取值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import re txt = ''' 我是你的正正老师 13800001111 13300001111 13400 136123123 1510000134 万门大学 .*.*&#$ ''' pattern1 = r '.{3}' #.任何字符{3}要满足3个任意字符(.)联在一起 result1 = re.findall(pattern1,txt) print (result1) |
输出结果:
^规定数据从头开始取值,按行取值用re.M=Multilines多行取法,就是一行一行取
1 2 3 4 5 6 7 8 9 10 11 | import re txt = """张三 python工程师 李四 java工程师 王五五 前端工程师""" # findall()函数的参数 re.M=Multilines多行取法,就是一行一组取 # ^规定从头开始取 pattern1 = r '^.{2,3}' #.任何字符{3}要满足3个任意字符(.)联在一起 result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:
$ 规定数据从末尾开始取值
1 2 3 4 5 6 7 8 9 | import re txt = """张三 python工程师 8000 李四 java工程师 10000 王五五 前端工程师 12000""" pattern1 = r '.{5}$' # $任何字符{5}要满足5个任意字符(.)联在一起,从末尾开始取值 result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:机械式取值
从末尾开始取数字\d取数字+出现的都取
1 2 3 4 5 6 7 8 9 | import re txt = """张三 python工程师 8000 李四 java工程师 10000 王五五 前端工程师 12000""" pattern1 = r '\d+$' # $从末尾开始取数字\d取数字+出现的都取 result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:
*代表全部都取值,当未取到值时为空
1 2 3 4 5 6 7 8 9 | import re txt = """张三 python工程师 8000 李四 java工程师 10000 王五五 前端工程师 12000""" pattern1 = r '\d*$' # $从末尾开始取数字\d取数字+出现的都取 result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:
1 2 3 4 5 6 7 8 9 | import re txt = """张三,销售总监,5000,3000 李四,销售经理,4000,2000 王五五,渠道经理,3500,1000""" pattern1 = r ',\d+,' # 会取到, result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:
限制输出某一部分
1 2 3 4 5 6 7 8 9 | import re txt = """张三,销售总监,5000,3000 李四,销售经理,4000,2000 王五五,渠道经理,3500,1000""" pattern1 = r ',(\d+),' # 不会取到,只输出分组中的内容 result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:
1 2 3 4 5 6 7 8 9 | import re txt = """张三,销售总监,5000,3000 李四,销售经理,4000,2000 王五五,渠道经理,3500,1000""" pattern1 = r ',(\d+),(\d+)' # 会取到, result1 = re.findall(pattern1,txt,re.M) print (result1) |
输出结果:输出一个列表
\w 匹配包括下划线的任何单词字符
手机号匹配(1)首先手机号第一位1开头(2)拟定第二位满足3 5 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import re phones = ''' 13800001111 13900004321 15112341234 14100001234 12900003333 1c200005678 ''' pattern1 = r '1[3,5,8]\d{9}' # 会取到, result1 = re.findall(pattern1,phones) print (result1) |
输出结果:
匹配a-e A-E开头的英文单词与匹配不是a-e A-E开头的英文单词
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import re words = '''love apple bus study actor great Air Business strange python java english China ''' pattern1 = r '^[a-eA-E].+' # 从头开始取因为单词是一个一个的 result1 = re.findall(pattern1,words,re.M) print (result1) pattern2 = r '^[^a-eA-E].+' # 从头开始取因为单词是一个一个的 result2 = re.findall(pattern2,words,re.M) print (result2) |
输出结果:
匹配英文单词进行取值
1 2 3 4 5 6 7 8 | import re words = '''love apple bus study actor great Air Business strange python java english China ''' pattern1 = r '[a-eA-E]\w+' # 从头开始取因为单词是一个一个的 result1 = re.findall(pattern1,words,re.M) print (result1) |
输出结果:
如果一个单词或者一端需要匹配的文字,被切断行了,使用re.S进行匹配
1 2 3 4 5 6 7 8 9 | import re msg = '''我到万门 大学学习Python ''' pattern1 = '到.*学*' result1 = re.findall(pattern1,msg,re.S) print (result1) |
输出结果:
取完整一句话中的空格和回车用\s取
1 2 3 4 5 6 7 8 | import re words = '''我是 来自 一个 万门 大学 的 对 P ython 感兴趣的 纯爷们 或 小姐姐''' pattern1 = '\s+' result1 = re.findall(pattern1,words) print (result1) |
输出结果:
取完整一句话中的非空格和回车用\S取
1 2 3 4 5 6 7 8 9 10 | import re words = '''我是 来自 一个 万门 大学 的 对 P ython 感兴趣的 纯爷们 或 小姐姐''' pattern1 = '\S+' result1 = re.findall(pattern1,words) print (result1) newres = ''.join(result1) print (newres) |
输出结果:
使用|作为或or 双多条件匹配,if and or
1 2 3 4 5 6 7 8 9 10 11 12 13 | import re words = ''' 北京程序员工资10000元/月 上海程序员工资12000块/月 深圳程序员工资9500圆/月''' pattern1 = r '\d+元|\d+块|\d+圆' # 使用|作为或or 双多条件匹配,if and or result1 = re.findall(pattern1,words) print (result1) pattern2 = r '\d+[元,块,圆]' result2 = re.findall(pattern2,words) print (result2) |
输出结果:
贪婪模式<.*>和非贪婪模式<.*?>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import re # -----正则 .* 的贪婪模式 # -----正则 .*? 非贪婪模式 # -----我们就拿一个简单的网页取值来说(爬虫的第二级数据获取) html = "<html><header><title>万门大学</title></header><body><h1>Hello world</h1></body></html>" #-----1 用<>做定位 #-----2 用<.*>取里边的值 pattern1 = r '<(.*)>' # 使用|作为或or 双多条件匹配,if and or result1 = re.findall(pattern1,html) print (result1) pattern2 = r '<(.*?)>' # 使用|作为或or 双多条件匹配,if and or result2 = re.findall(pattern2,html) print (result2) |
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import re # -----正则 .* 的贪婪模式 # -----正则 .*? 非贪婪模式 # -----我们就拿一个简单的网页取值来说(爬虫的第二级数据获取) html = """ <html> <header> <title>万门大学</title> </header> <body> <h1>Hello world</h1> </body> </html> """ #-----1 用<>做定位 #-----2 用<.*>取里边的值 pattern1 = r '<(.*)>' # 使用|作为或or 双多条件匹配,if and or result1 = re.findall(pattern1,html) print (result1) pattern2 = r '<(.*?)>' # 使用|作为或or 双多条件匹配,if and or result2 = re.findall(pattern2,html) print (result2) |
输出结果:
match和简单split
1 2 3 4 5 6 7 8 9 10 | import re qq1 = '1234@qq.com 45532441@qq.com 4134abc234@qq.com a123324844@qq.com 15532441@qq.com 14532433@qq.cn' print (qq1.split( " " )) #切割也使用正则表达式 qq2 = '1234@qq.com*45532441@qq.com/4134abc234@qq.com a123324844@qq.com&15532441@qq.com#14532433@qq.cn' pattern = r '[*/&#]' res = re.split(pattern,qq2) print (res) |
输出结果:
1 2 3 4 5 6 7 8 9 10 | import re mail = ' aaa@qq.cn bb@wanmen.org ccc@cc.com' # ----现在的目标是想用.作为一个“坐标”来取值,但是,又是一个正则通配符号 pattern = r '@.*?\.\w+' # ---解释一下 @这个是起点坐标.*? 是一个惰性 看到 一组 @ .之间的就取 # ---接着 \.就是 实际上一个.是一个标准符号坐标,不是正则通配符,他就代表它自己 # ---\w+剩下的所有字符都通配,遇到 空格就停止 res = re.findall(pattern,mail) print (res) |
输出结果:
特殊情况,掐头去尾,锁定固定长度,使用开头结尾标示^ $
1 2 3 4 5 6 7 8 9 10 11 | import re patt1 = r '^a[1,2]$' res1 = re.match(patt1, 'a1' ) res2 = re.match(patt1, 'a2' ) res3 = re.match(patt1, 'a1111' ) res4 = re.match(patt1, 'a2222' ) print (res1) print (res2) print (res3) print (res4) |
输出结果:
手机号正则表达式匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 | import re # 手机号规则 # 做正则的时候一定要先拆出来你要匹配的规则 一般前三位是一个规则 # 然后后边8位数字 # 当然位数只有能有数字 pattern1 = r '^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|4|5|6|7|8|9])\d{8}$' res = re.match(pattern1, '15683039101' ) print (res) print ( bool (res)) if res: print ( "找到了" ) else : print ( "没找到" ) |
输出结果:
邮箱匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 | import re # 手机号规则 # 做正则的时候一定要先拆出来你要匹配的规则 一般前三位是一个规则 # 然后后边8位数字 # 当然位数只有能有数字 pattern1 = r '^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$' res = re.match(pattern1, '_dhadj@asdf.com' ) print (res) print ( bool (res)) if res: print ( "找到了" ) else : print ( "没找到" ) |
输出结果:
网页网站正则表达式匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import re articles = [ "<li><a href='http://www.xiaole8.com/shangganwenzhang'>伤感文章</a></li>" , "<li><a href='http://www.xiaole8.com/aiqingwenzhang'>爱情文章</a></li>" , "<li><a href='http://www.xiaole8.com/ganrengushi'>感人故事</a></li>" , "<li><a href='http://www.xiaole8.com/qingganmeiwen'>情感美文</a></li>" , "<li><a href='http://www.xiaole8.com/lizhiwenzhang'>励志文章</a></li>" , "<li><a href='http://www.xiaole8.com/renshengzheli'>人生哲理</a></li>" , "<li><a href='http://www.xiaole8.com/gaoxiaowenzhang'>搞笑文章</a></li>" , "<li><a href='http://www.xiaole8.com/jingdianwenzhang'>经典文章</a></li>" , "<li><a href='http://www.xiaole8.com/qinqingwenzhang'>亲情文章</a></li>" , "<li><a href='http://www.xiaole8.com/youqingwenzhang'>友情文章</a></li>" , ] pattern = r "<li><a href='(.*?)'>(.*?)</a></li>" output = {} for article in articles: res = re.findall(pattern,article) print (res[ 0 ][ 0 ]) output[res[ 0 ][ 1 ]] = res[ 0 ][ 0 ] print (output) |
输出结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)