学习笔记-Python开发-023_正则表达式简介

我们已经接触到了很多次在文本信息中提取数据的情况,但是总是觉得split()这些方法太麻烦,并且无法应对所有的情况,例如

text = "楼主太牛逼了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,搞起来呀"

我们要提取文本中的邮箱和手机号

import re

text = "楼主太牛逼了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,搞起来呀,159028040130"

phone_list = re.findall("1[3|5|8|9]\d{9}",text)
print(phone_list)

正则的作用就是可以帮我们提取想要的数据,和判断是否是我们需要的格式的数据

1[3|5|8|9]\d{9}
这段就是正则表达式的规则:
\d 数字
{9} 代表数字要出现9次

需要注意的是:正则表达式属于通识知识点,不止可以在python中使用,但为了方便,将会使用python进行演示

1 字符相关

1.1 匹配一段固定的文字

如果要匹配一段固定的文字,那么直接将文字在正则表达式中写入即可

import re
text = "你好wupeiqi,阿斯顿发wupeiqasd 阿士大夫能接受的wupeiqiff"
data_list= re.findall("wupeiq",text)
print(data_list) # ['wupeiq', 'wupeiq', 'wupeiq']
print(len(data_list)) # 3 计算这个词在文本中出现的次数

1.2 匹配一段文本中多个单字符

例如匹配a、b、c三个字符

import re
text = "asdqwuiochrasbkdcuhq87iwgdakjdwqiohdeasblkjncfqewasd"
data_list = re.findall("[abc]",text)
print(data_list) # ['a', 'c', 'a', 'b', 'c', 'a', 'a', 'b', 'c', 'a']

1.3 匹配与字符进行组合的字符

例如匹配与as开头后跟d\b\c的字符

import re
text = "asdqwuiascochrasbkdcuhq87asciwgdakjdwqiohdeasblkjncfqewasd"
data_list = re.findall("as[dbc]",text)
print(data_list) # ['asd', 'asc', 'asb', 'asc', 'asb', 'asd']

1.4 匹配除了[字符]之外的字符

例如匹配除了abc之外的字符

import re
text = "asdqwcfqewasd"
data_list = re.findall("[^abc]",text)
print(data_list) # ['s', 'd', 'q', 'w', 'f', 'q', 'e', 'w', 's', 'd']

1.5 匹配字母或者数字区间的任意字符

import re
text = "dasa123we10973ag"
# 匹配a-d的所有字符
datelist = re.findall("[a-d]",text)
print(datelist) # ['d', 'a', 'a', 'a']
# 匹配3-7的所有字符
datelist = re.findall("[3-7]",text)
print(datelist) # ['3', '7', '3']
# 匹配a开头与字母搭配的所有字符
datelist = re.findall("a[a-z]",text)
print(datelist) # ['as', 'ag']
# 也可以匹配以a结尾搭配的所有字符
datelist = re.findall("[a-z]a",text)
print(datelist) # ['da', 'sa']

1.6 . 代指除换行符以外的任意字符

import re

text = "alexraotroor!otadr测omin"
data_list = re.findall("r.o", text)
print(data_list) # ['rao', 'roo', 'r!o', 'r测o']

# 贪婪匹配 -> 匹配ro中间任意多个字符(尽量多的匹配)
data_list = re.findall("r.+o",text)
print(data_list) # ['raotroor!otadr测o'] ro中间的所有字符都被匹配到了
# 非贪婪匹配 -> 匹配ro中间任意多个字符(最短的匹配)
data_list = re.findall('a.+?r',text)
print(data_list) # ['alexr', 'aotr', 'adr']

1.7 \w 代指字母或数字或下划线(汉字)

import re

text = "雅ss思你sdaw的a歌"
data_list = re.findall("思\w+a", text)
print(data_list) # ['思你sdaw的a']

1.8 \d 代指数字

import re
text = "56asdra7s6dtas8"
data_list = re.findall("a\d",text)
print(data_list) # ['a7'] a开头的数字

1.9 \s 代指任意的空白符,包括空格、制表符等

import re

text = "root admin add admin"
data_list = re.findall("a\w+\s\w+", text)
print(data_list) 
# ['admin add'] 匹配a开头后面是字母数字下划线(不限个数),然后是空白符,然后再试字母数字下划线(不限个数)

2 次数相关

2.1 * 重复0次或更多次

import re
text = "他是大B个,确实是个大2B,大2222B,大66666B。"
# 正则解析: 大 2*(0次或n次2) B
data_list = re.findall("大2*B", text)
print(data_list) ['大B', '大2B', '大2222B']

2.2 + 重复1次或更多次

import re

text = "他是大B个,确实是个大2B,大3B,大66666B。"
# 正则解析: 大 \d(数字+)+(重复1次或n次数字) B
data_list = re.findall("大\d+B", text)
print(data_list) # ['大2B', '大3B', '大66666B']

2.3 ? 重复0次或1次

import re

text = "他是大B个,确实是个大2B,大3B,大66666B。"
# 正则解析: 大 \d(数字)?(数字重复0次或1次) B
data_list = re.findall("大\d?B", text)
print(data_list) # ['大B', '大2B', '大3B']

2.4 {n} 重复n次

import re

text = "楼主太牛逼了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,搞起来呀"
# 正则解析: 151312 \d(数字){数字有5位或者重复5次}
data_list = re.findall("151312\d{5}", text)
print(data_list) # ['15131255789']

2.5 {n,} 重复n次或更多次

import re

text = "楼主太牛逼了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,搞起来呀"
# 正则解析: \d(数字){9,}(数字有9位以上)
data_list = re.findall("\d{9,}", text)
print(data_list) # ['442662578', '15131255789']

2.6 {n,m} 重复n到m次

import re

text = "楼主太牛逼了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,搞起来呀"
# 正则解析: \d(数字){10,15}(数字有十到十五位)
data_list = re.findall("\d{10,15}", text)
print(data_list) # ['15131255789']

3 括号

3.1 提取数据区域

import re
text = '我的电话号码是13724562451,她的电话号码是159092145274,邮箱是4215523153@qq.com'

'''需求1:匹配电话号码'''
## 已知电话号码是11位,1开头3\5\7\9后跟9位数
data_list = re.findall("1[3|5|7|9]\d{9}",text)
print(data_list) # ['13724562451', '15909214527']

'''需求2:需要将中间四位数隐藏 , 提取开头三位数和结尾四位数'''
## 需要使用括号,将后面的9位数拆分位\d{1}\d{4}\d{4}
### 使用括号(1[3|5|7|9]\d{1})表示提取前三位数
### 使用括号(\d{4}) 表示提取后四位数
data_list = re.findall("(1[3|5|7|9]\d{1})\d{4}(\d{4})",text)
print(data_list) # [('137', '2451'), ('159', '4527')]
for v1,v2 in data_list:
    phone_number = "{}****{}".format(v1,v2)
    print(phone_number)
# 137****2451
# 159****4527

'''需求3:获取隐藏号码的同时,也要获取真实号码交给系统'''
## 括号是可以嵌套的
data_list = re.findall("((1[3|5|7|9]\d{1})\d{4}(\d{4}))",text)
print(data_list) # [('13724562451', '137', '2451'), ('15909214527', '159', '4527')]

3.2 获取指定区域 + 或条件

import re

text = "楼主15131root太牛15131alex逼了,在线想要 442662578@qq.com和xxxxx@live.com谢谢楼主,手机号也可15131255789,搞起来呀"
# 正则解释:15131 (2开头数字重复五次) 或者 (r开头字母或者数字或者下划线太结尾) 提取括号里的内容
data_list = re.findall("15131(2\d{5}|r\w+太)", text)
print(data_list)  # ['root太', '255789']

4 起始和结束

上述示例中都是去一段文本中提取数据,只要文本中存在即可。

它除了提取,也可以做用户输入的校验,如果要求用户输入的内容必须是指定的内容开头和结尾,比就需要用到如下两个字符。

^ 开始
$ 结束

案例:简易sql注入防御waf

import re
text = 'id = -1 union select * from user and 1=1'
# 判断输入中是否有and和or
inp_list = re.findall("^(.+)and(.+)|(.+)or(.+)$",text)
print(inp_list)
if inp_list:
    print("您的输入非法,我们已经记录您的ip地址和请求")

5 特殊字符

由于正则表达式中 * . \ { } ( ) 等都具有特殊的含义,所以如果想要在正则中匹配这种指定的字符,需要转义,例如:

import re

text = "我是你{5}爸爸"
data = re.findall("你\{5\}爸", text)
print(data)

6 分组别名

如果我们的正则表达式会提取非常多不同目的的数据,而它们混迹在输出的列表元组中,非常不直观

import re

text = "dsf130429191912015219k13042919591219521Xkk"

data_list = re.findall("\d{6}(\d{4})(\d{2})(\d{2})\d{3}[\d|X]",text)
print(data_list) # [('1919', '12', '01'), ('1959', '12', '19')]

# 输出字典只能使用finditer
data_list = re.finditer("\d{6}(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2})\d{3}[\d|X]",text)
for item in data_list:
    print(item.groupdict())
'''输出结果
{'year': '1919', 'month': '12', 'day': '01'}
{'year': '1959', 'month': '12', 'day': '19'}
'''
posted @ 2023-02-26 22:39  kinghtxg  阅读(10)  评论(0编辑  收藏  举报