35.正则模块

1.正则表达式

正则表达式利用一些特殊的符号组合去字符串中筛选出符合条件的数据。
正则表达式是一门独立的语言,在Python中使用需要借助re模块。

2.字符组

ps:字符串默认只能单个单个字符匹配。
字符组的特征是用中括号括起来。

2.1含义

字符组 含义
[0123456789] 简写[0-9] 匹配0 - 9之间的任意一个数字
[a-z] 匹配小写字符 a - z 之间的任意一个字母
[A-Z] 匹配小写字符 A - Z 之间的任意一个字母
[a-zA-Z0-9] 匹配所有数字与字母

2.2练习

[1]   1111154545  五个1被匹配
[111] 1111154545  五个1被匹配     对个1看成是一个1

[0-9]             10个数字被匹配 

[a-z] asdsasdasd  10个字符被匹配 
[ab-z] 这样写法没什么意义 功能同上

[a-zA-Z0-9]	SDAF156SA1DF65AS6DF51AS6D5sad5a6   32个字符

3.特殊符号

3.1含义

特殊字符 含义
. 匹配除换行符以外的任意字符
\d 匹配数字
^ 以什么开头的字符
$ 以什么结尾的字符
^xxx$ 组合使用,精准查找的数据
| 逻辑或 a|b 匹配a或者b
() 匹配括号内的表达式,也表示一个组
[···] 匹配字符组中的字符
[^···] 取反 匹配除了 字符组中字符 的所有字符

3.2练习

..    aasdadasdasfddfaaa  两个字符的组合  出现了9  成对匹配
\d    0123456789          匹配到10个结果
\d\d  0123456789          匹配到5个结果
^a    asasa               匹配到1个结果
a$    asasa               匹配到1个结果
^kid$  kid                匹配到1个结果, 除了kid其它的都不行
1|2|3|4|5  12315131535    匹配到11个结果  
ad   
(ad) --> ad    adasaad    匹配到2个结果   单个字符与前后组合 匹配
[ad] --> [a-d] adasaad    匹配到6个结果
[^ad]	       adasaad    匹配到1个结果

4.量词

4.1说明

1.表达式在没有量词修饰的情况下都是与单个字符进行匹配
2.量词必须结合(字符组,特殊符号···)一起使用,不能单独出现。
3.量词只能影响前面的一个表达式,eg: ab+  只能影响b。

4.2符号

量词默认情况下都是贪婪匹配
量词 含义
* 重复零次或者更多次
+ 重复一次或者更多次
重复零次或一次
{n} 重复n次
{n, } 重复n次或更多次
{n,m} 重复n到m次

4.3练习

a.*    asaaa           匹配到 1 条结果    .表示一个除换行符的任意字符,*重复多次
a.+    asaaa           匹配到 1 条结果    .表示一个除换行符的任意字符,+重复多次
a.?    asaaa           匹配到 3 条结果    单个字符与前后组合 匹配
a{
    
    2}   asaaa           匹配到 1 条结果    两个字符的组合 成对匹配
a{
    
    1,}                  匹配到 2 条结果    如果连续重复多个出现算一个,否则按单个算
a{
    
    1,2} asaaa           匹配到 3 条结果    如果连续两个重复出现算一个,否则按单个算

5.贪婪匹配

5.1说明

正则表达式中的量词默认都是'贪婪匹配'
贪婪匹配会尽可能的多匹配
惰性匹配尽可能的少匹配

5.2练习

贪婪匹配     .*
<a>www.baidu.com</a>   <.* 将a便签全部元素匹配
惰性匹配    .*?
<a></a>                <.*?> 将a标签匹配出来
^[1-9]\d{
    
    13,16}[0-9x]$

1-9开头    一个数
\d{
    
    13-16}  13-16位数字
0-9或x结尾  一个位字符数字或字符
最低15位字符 最高18
^[1-9]\d{
    
    14}(\d{
    
    2}[0-9x])?$
1-9开头  一个数字
\d{
    
    14}  14个数字
\d{
    
    2} 两个数字 [0-9x] 一个数字或字符 ? 出现一次 或者不出现 
最低15位字符 最高18
^([1-9]\d{
    
    16}[0-9x]|[1-9]\d{
    
    14})$
[1-9]  1位数字
\d{
    
    16} 16位数字
[0-9x]  1个数字或1个字符
118



[1-9]  1位数字
\d{
    
    14} 14位数字
15

6.取消转义

6.1说明

在原生正则表达式中\加上某些字符会产生特殊的含义。
使用\抑制\  :换行 \n  ---> \\n
一个\抑制1\
Python中取消转义,也能使用\,但是推荐使用r'\n\a\t' 

6.2练习

\\n     ---匹配--->  \n  
\\\\n   ---匹配--->  \\n  

image-20211125151446550

image-20211125151618670

7.re模块

Python内置re模块出来正则表达式。

7.1常用方法


.findall('正则表达式','匹配的文本') 方法 
	根据正则匹配符合条件的数据,将数据存入一个列表中,如果没有匹配到,则返回一个空列表。
	
.search('正则表达式','匹配的文本') 方法
	根据正则匹配符合条件的数据,匹配到一个则返回,结果为一个对象,通过.group()取值
	如果无法匹配则返回None,在group()则会报错。

.match('正则表达式','匹配的文本') 方法
	根据正则匹配符合条件的数据,从头匹配到尾。结尾为一个对象,通过.group()取值。
	如果无法匹配则返回None,在group()则会报错。
import re

# 存在
res = re.findall('a', 'abca')
print(res)  # ['a', 'a']   

# 不存在
res = re.findall('z', 'abca')
print(res)  # []



# 存在
res = re.search('a', 'abca')
print(res)  #  返回一个对象 <_sre.SRE_Match object; span=(0, 1), match='a'>
print(res.group())  # a

# 不存在
res = re.search('z', 'abca')
if res:
    print(res.group())  # 为空不执行
"""
print(res.group())  # 直接报错
"""



# 存在
res = re.match('a', 'abca')
print(res)  # 返回一个对象 <_sre.SRE_Match object; span=(0, 1), match='a'>
print(res.group())  # a

# 不存在
res = re.match('z', 'abca')
print(res)  # None
if res:
    print(res.group())  # 不执行

7.2其他方法

1.切分
.split('字符', '匹配的文本')  
maxsplit 参数设置切的次数。
按字符切分, 左右两边有值存入列表中。
有一边没有值会被切一个空字符出来
import re

res = re.split('b', 'acbac')  # 按b切分
print(res)  # ['ac', 'ac'] 左右两边有值存入列表中

res = re.split('a', 'acbac')  # 按b切分
print(res)  # ['', 'cb', 'c'] 有一边没有值会被切一个空字符出来




res = re.split('[ab]', 'acbac', maxsplit=1)  # 按a切分
print(res)  # ['', 'cbac']

res = re.split('[ab]', 'acbac', maxsplit=2)  # 按a切分
print(res)  # ['', 'c', 'ac']

res = re.split('[ab]', 'acbac')  # 按a切分
print(res)  # ['', 'c', '', 'c']

"""
先按a切得 '' 'cbac'
在按b切得 '' 'c' 'ac'   
在按a切得 '' 'c' '' 'c'
"""
2.替换
.sub('正则表达式', '替换的字符', '匹配的文本', 次数) 
默认替换所有,也可以写入参数控制次数。
相当于 repleace替换


.subn('正则表达式', '替换的字符', '匹配的文本', 次数) 
返回元组,并提示替换次数。
import re

res = re.sub('a', 'b', 'abca')
print(res)  # bbcb

res = re.subn('a', 'b', 'abca')
print(res)  # ('bbcb', 2)

3.指定规则
变量 = re.compile('正则表达式')
多个位置需要使用同一个表达式将表达式编译成一个固定的规则。
在用的时候直接使用。
import re

res = re.compile('\d+')
print(res)  # re.compile('\\d+')


print(res.findall('123'))  # ['123']


print(res.search('123'))  # <_sre.SRE_Match object; span=(0, 3), match='123'>

print(res.match('123'))  # <_sre.SRE_Match object; span=(0, 3), match='123'>
4.匹配
.findall('正则表达式','匹配的文本') 方法 
根据正则匹配符合条件的数据,数据的格式为迭代器对象存对象的形式。
import re

res = re.finditer('\d+', '1')
print(res)  # <callable_iterator object at 0x0000026323273550>
print(res.__next__())  # <_sre.SRE_Match object; span=(0, 1), match='1'>

res = re.finditer('\d+', '123456789')
res = [i.group() for i in res]
print(res)  # ['123456789']
5.分组
import re

res = re.search('^[1-9](\d{1})(\d{2}[0-9x])?$','12345')
if res:
    print(res.group())  # 12345
    print(res.group(0))  # 12345
    print(res.group(1))  # 2
    print(res.group(2))  # 345
6.无名分组
findall 会优先显示分组的。
在括号没加上?:取消优先展示。
import re

# 优先展示
res = re.findall('^[1-9](\d{1})(\d{2}[0-9x])?$','12345')
if res:
    print(res)  # [('2', '345')]


# 取消
res = re.findall('^[1-9](?:\d{1})(\d{2}[0-9x])?$','12345')
if res:
    print(res)  # ['345']

# 取消
res = re.findall('^[1-9](?:\d{1})(?:\d{2}[0-9x])?$','12345')
if res:
    print(res)  # ['12345']
7.有名分组
在分组内使用?P<名称> 起别名。
.grounp('名称') 获取值。
import re


res = re.search('^[1-9](?P<xx>\d{1})(?P<yy>\d{2}[0-9x])?$','12345')
if res:
    print(res.group('xx'))  # 2
    print(res.group('yy'))  # 345

8.练习

判断是否为手机号
1.必须是11
2.必须是纯数字
3.必须符合手机号的排布  15 16 18 19
# 1.获取用户输入
phone = input('输入手机号>>>:').strip()
# 判断位数
if len(phone) == 11:
    # 判断输入是否为纯数字
    if phone.isdigit():
        # 判断是否以什么开头
        if int(phone[0:2]) in [15, 16, 18, 19]:
            print('输入合法!')
        else:
            print('不是手机号')
    else:
        print('不是纯数字')
else:
    print('位数不对')
import re
in_data = input('输入号码>>>:')
if re.findall('^[15|16|18|19]\d{9}', in_data):
    print('输入正确!')
else:
    print('输入不合法!')
红牛分公司信息
import re

with open(r'html.txt', mode='r', encoding='utf8') as f1:
    data = f1.read()
"""
<h2>红牛豫南分公司</h2>
<p class='mapIco'>驻马店市乐山路与通达路交叉口爱家会展国际公寓5B1105</p>
<p class='mailIco'>463000</p>
<p class='telIco'>0396-3336611</p>
"""

name_list = re.findall('<h2>(.*?)</h2>', data)
# print(name_list)

addr_list = re.findall("<p class='mapIco'>(.*?)</p>", data)
# print(addr_list)

email_list = re.findall("<p class='mailIco'>(.*?)</p>", data)
# print(email_list)

phone_list = re.findall("<p class='telIco'>(.*?)</p>", data)
# print(phone_list)

list1 = zip(name_list, addr_list, email_list, phone_list)
list1 = list(list1)
for message in list1:
    print("""
        公司名称   %s
        公司地址   %s
        公司邮箱   %s
        公司号码   %s
    """ % (message[0], message[1], message[2], message[3]))

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/121522130