19.3 Python入门之正则表达式

正则表达式


当写一个脚本来自动获取最新的代理IP地址,目标URL:http://cn-proxy.com/


很难定位到IP及对应端口的位置,只有class = "sortable"是两个IP表格唯一的特性

产生需求,即通过IP地址特征(四段数字组成,每段数字范围0-255,分别由三个点号隔开)来寻找IP地址,正则表达式应运而生,其是描述这些复杂规则的工具


re模块


Python通过re模块来实现正则表达式


>>>import re

>>>re.search(r'Fish','I love Fish')

<_sre.SER_Match object;span=(7,12),match = 'Fish'>


分析:

search()方法用于在字符串中搜索正则表达式模式第一次出现的位置,结果为(7,12)


第一个参数是正则表达式模式,即描述的搜索规则,使用原始字符串来写


找到后返回的范围下标以0开始,找不到,则返回None


通配符


通配符即可表示任何字符,如所有Word类型的文件为*.docx

正则表达式的通配符用点号(.)来表示,可匹配除了换行符的任何字符


>>>re.search(r'.','I love Fish')

<_sre.SER_Match object;span=(0,1),match = 'I'>

>>>re.search(r'Fish','I love FishC')

<_sre.SER_Match object;span=(7,12),match = 'FishC'>


反斜杠


若想单单匹配点号,则加上反斜杠,表示消除元字符的特殊功能


>>>re.search(r'\.','I love Fish.com')


反斜杠也可以使普通字符拥有特殊能力,如(\d)表示匹配数字


>>>re.search(r'\d','123 I love Fish')

<_sre.SER_Match object;span=(0,1),match = '1'>


粗糙的匹配一个IP地址可以如下写法


>>>re.search(r'\d\d\d.\d\d\d.\d\d\d.\d\d\d','other 192.168.011.111other')


但上述不规范,因为IP数字范围是0-255,而不是000-999


字符类


字符类用来表述一个字符的范围,使用中括号将内容包起来就是字符类,含义是只要匹配到这个字符类的任何字符,结果算作匹配


如想要匹配元音字母,则

>>>>>>re.search(r'[aeiou]','I love Fish')

<_sre.SER_Match object;span=(3,4),match = 'o'>


因为正则表达式区分大小写,所以I虽然是元音字母,但是没有匹配


解决方法:


法一:关闭大小写敏感模式


法二:修改字符类

>>>>>>re.search(r'[aeiouAEIOU]','I love Fish')


在中括号内可使用小横杆来表示范围,包括数字和字母


>>>>>>re.search(r'[a-z]','I love Fish')

>>>>>>re.search(r'[0-2][0-5][0-5]','I love Fish')


[01]与[0-1]等价


重复匹配


大括号对元字符实现重复匹配的功能


>>>re.search(r'ab{3}c','abbbc')

<_sre.SER_Match object;span=(0,5),match = 'abbbc'>


>>>re.search(r'ab{3}c','abbbbbc') #匹配不了


重复的次数取一个范围


>>>re.search(r'ab{3,5}c','abbbbbc')

<_sre.SER_Match object;span=(0,7),match = 'abbbbbc'>


>>>re.search(r'ab{3,5}c','abbbc')

<_sre.SER_Match object;span=(0,5),match = 'abbbc'>



>>>re.search(r'[0-255]','188')

<_sre.SER_Match object;span=(0,1),match = '1'>


>>>re.search(r'[0-2][0-5][0-5]','188')


正则表达式匹配的是字符串,所以数字对于字符来说只有0-9,123由‘1’,‘2’,‘3’三个字符构成,[0-255]字符类表示0-2还有两个5,所以匹配的是0125四个数字中任何一个


匹配0-255范围的数字,正确写法是

>>>re.search(r'[0-1]\d\d\|2[0-4]\d|25[0-5]','188') #000-199,200-249,250-255

<_sre.SER_Match object;span=(0,3),match = '188'>


匹配IP地址


>>>re.search(r'([0-1]\d\d|2[0-4]\d|25[0-5]\.){3}([01]\d\d|2[0-4]\d|25[0-5])',''other192.168.1.other')


{3}表示需要重复匹配三次才成功


上例忽视了1不会写出001这一点,忽略位数的影响,所以最终版为


re.search(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])',''other192.168.1.other')


[01]{0,1}\d{0,1}\d表示最后一位一定要有(没有的话还叫数字吗),但百位和十位可有可无


特殊符号及用法


正则表达式以字符串的形式描述,其强大之处在于特殊符号,特殊符号定义了字符集合,子组匹配,模式重复次数。


元字符


包括 . ^ $ * + ? {} [] \ | ()


(.)点号表示匹配除换行符外的任何字符

(|)管道符类似逻辑或操作


>>>re.search(r"Fish(C|D)","FishC")

<_sre.SER_Match object;span=(0,5),match = 'FishC'>


(^)表示匹配字符串的开始位置,即目标字符串出现在开头才会匹配


>>>re.search(r"^Fish","Fish.com")

<_sre.SER_Match object;span=(0,4),match = 'Fish'>

>>>re.search(r"^Fish","I love Fish.com")  #None


($)表示匹配字符串的结束位置,即目标字符串出现在末尾才会匹配


>>>re.search(r"FishC$","love FishC")

<_sre.SER_Match object;span=(5,10),match = 'FishC'>


小括号本身是一对元字符,括号内的正则表达式称为一个子组,子组可当做一个整体,例如在后面对其引用


反斜杠


反斜杠若后面数字数1-99,则表示引用序号对应的子组的字符串,若后面数字是0开头或者是三位数字,则表示八进制数,表示的是八进制数所对应的ASCII码字符


>>>re.search(r"(FishC)\1","FishCFishC.com")


\1表示引用前边序号为1的子组(第一个子组),所以r"(FishC)\1"相当于r"FishCFishC",所以匹配的是要有连续两个FishC的内容,才能成功匹配


若\后面添加的是数字0开头或者三位数,则把这三位数当做一个八进制数


>>>re.search(r"\141FishC","aFishC.com")

八进制141对应的ASCII码为小写字母a

>>>re.search(r"(FishC)\060","FishC0.com")

八进制060对应的ASCII码为数字0



[]这对元字符


表明是生成字符类,实际是一个字符集合,其内部的元字符都失去特殊功能,如同反斜杠加上元字符一样



>>>re.search(r"[.]","FishC.com")

<_sre.SER_Match object;span=(5,6),match = '.'>




字符类内部的元字符都失去特殊功能,但也有几个特殊情况


1)小横杠表示范围


>>>re.findall(r"[a-z]","FishC.com")

['i','s','h','c','o','m']

>>>findall表示找出所有匹配内容,并将结果返回为一个列表


2)反斜杠,例如\n表示匹配换行符


3)脱字符(^)表示取反

>>>re.findall(r"[^a-z]","FishC.com")

['F','C','.']


大括号,表示重复次数


"FishC{3}"等价于"FishCCC"

(FishC){3}"等价于"FishCFishCFishC"

(FishC){1,3}表示重复的次数为一次或三次,注意{1,3}间不能有空格


正则表达式不能随便用空格,表示重复的元字符还有:*,+和?


*表示{0,},+表示{1,},问号表示{0,1},同等情况推荐使用这些符号,简洁且效率比使用大括号高些






猜你喜欢

转载自blog.csdn.net/lwz45698752/article/details/79252626