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 - 9 x ] $
1 - 9 开头 一个数
\ d {
13 - 16 } 13 - 16 位数字
0 - 9 或x结尾 一个位字符数字或字符
最低 15 位字符 最高 18
^ [ 1 - 9 ] \ d {
14 } ( \ d {
2 } [ 0 - 9 x ] ) ?$
1 - 9 开头 一个数字
\ d {
14 } 14 个数字
\ d {
2 } 两个数字 [ 0 - 9 x ] 一个数字或字符 ? 出现一次 或者不出现
最低 15 位字符 最高 18
^ ( [ 1 - 9 ] \ d {
16 } [ 0 - 9 x ] | [ 1 - 9 ] \ d {
14 } ) $
[ 1 - 9 ] 1 位数字
\ d {
16 } 16 位数字
[ 0 - 9 x ] 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
7.re模块
Python内置re模块出来正则表达式。
7.1常用方法
. findall ( '正则表达式' , '匹配的文本' ) 方法
根据正则匹配符合条件的数据 , 将数据存入一个列表中,如果没有匹配到,则返回一个空列表。
. search ( '正则表达式' , '匹配的文本' ) 方法
根据正则匹配符合条件的数据,匹配到一个则返回,结果为一个对象,通过 . group ( ) 取值
如果无法匹配则返回None , 在group ( ) 则会报错。
. match ( '正则表达式' , '匹配的文本' ) 方法
根据正则匹配符合条件的数据,从头匹配到尾。结尾为一个对象,通过 . group ( ) 取值。
如果无法匹配则返回None , 在group ( ) 则会报错。
import re
res = re. findall( 'a' , 'abca' )
print ( res)
res = re. findall( 'z' , 'abca' )
print ( res)
res = re. search( 'a' , 'abca' )
print ( res)
print ( res. group( ) )
res = re. search( 'z' , 'abca' )
if res:
print ( res. group( ) )
"""
print(res.group()) # 直接报错
"""
res = re. match( 'a' , 'abca' )
print ( res)
print ( res. group( ) )
res = re. match( 'z' , 'abca' )
print ( res)
if res:
print ( res. group( ) )
7.2其他方法
1.切分
. split ( '字符' , '匹配的文本' )
maxsplit 参数设置切的次数。
按字符切分, 左右两边有值存入列表中。
有一边没有值会被切一个空字符出来
import re
res = re. split( 'b' , 'acbac' )
print ( res)
res = re. split( 'a' , 'acbac' )
print ( res)
res = re. split( '[ab]' , 'acbac' , maxsplit= 1 )
print ( res)
res = re. split( '[ab]' , 'acbac' , maxsplit= 2 )
print ( res)
res = re. split( '[ab]' , 'acbac' )
print ( res)
"""
先按a切得 '' 'cbac'
在按b切得 '' 'c' 'ac'
在按a切得 '' 'c' '' 'c'
"""
2.替换
. sub ( '正则表达式' , '替换的字符' , '匹配的文本' , 次数 )
默认替换所有,也可以写入参数控制次数。
相当于 repleace替换
. subn ( '正则表达式' , '替换的字符' , '匹配的文本' , 次数 )
返回元组,并提示替换次数。
import re
res = re. sub( 'a' , 'b' , 'abca' )
print ( res)
res = re. subn( 'a' , 'b' , 'abca' )
print ( res)
3.指定规则
变量 = re . compile ( '正则表达式' )
多个位置需要使用同一个表达式将表达式编译成一个固定的规则。
在用的时候直接使用。
import re
res = re. compile ( '\d+' )
print ( res)
print ( res. findall( '123' ) )
print ( res. search( '123' ) )
print ( res. match( '123' ) )
4.匹配
. findall ( '正则表达式' , '匹配的文本' ) 方法
根据正则匹配符合条件的数据 , 数据的格式为迭代器对象存对象的形式。
import re
res = re. finditer( '\d+' , '1' )
print ( res)
print ( res. __next__( ) )
res = re. finditer( '\d+' , '123456789' )
res = [ i. group( ) for i in res]
print ( res)
5.分组
import re
res = re. search( '^[1-9](\d{1})(\d{2}[0-9x])?$' , '12345' )
if res:
print ( res. group( ) )
print ( res. group( 0 ) )
print ( res. group( 1 ) )
print ( res. group( 2 ) )
6.无名分组
findall 会优先显示分组的。
在括号没加上? : 取消优先展示。
import re
res = re. findall( '^[1-9](\d{1})(\d{2}[0-9x])?$' , '12345' )
if res:
print ( res)
res = re. findall( '^[1-9](?:\d{1})(\d{2}[0-9x])?$' , '12345' )
if res:
print ( res)
res = re. findall( '^[1-9](?:\d{1})(?:\d{2}[0-9x])?$' , '12345' )
if res:
print ( res)
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' ) )
print ( res. group( 'yy' ) )
8.练习
判断是否为手机号
1. 必须是 11 位
2. 必须是纯数字
3. 必须符合手机号的排布 15 16 18 19
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)
addr_list = re. findall( "<p class='mapIco'>(.*?)</p>" , data)
email_list = re. findall( "<p class='mailIco'>(.*?)</p>" , data)
phone_list = re. findall( "<p class='telIco'>(.*?)</p>" , data)
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 ] ) )