初识正则
从得到的HTML代码中获取想要的数据,正则是一个有效的方法。
正则表达式测试工具:http://tool.oschina.net/regex/
在网页右侧选择“匹配Email地址”,就可以看到下方出现了文本中的E-mail。
正则表达式的匹配功能,就是用一定规则将特定的文本提取出来。
另外正则表达式不是Python独有的,它也可以用在其他编程语言中。Python的re库提供了整个正则表达式的实现。
match
常用的匹配方法,向它传入想要匹配的字符串,以及正则表达式,就可以检测这个正则表达式是否匹配字符串。
match方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就该返回成功的结果;否则,就返回None。
import recontent = 'Hello 123 4567 World_This is a Regex Demo'print(len(content))result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}', content)print(result)print(result.group())print(result.span())
运行结果
41<_sre.sre_match object span="(0," match="Hello 123 4567 World_This">Hello 123 4567 World_This(0, 25)
正则表达式示例
^Hello\s\d\d\d\s\d{4}\s\w{10}
开头的^匹配字符串的开头,也就是以Hello开头;\s匹配空白字符串,用来匹配目标字符串的空格;\d匹配数字,3个\d匹配123;再写1个\s匹配空格;后面4567,用\d{4}匹配。
在match方法中,第一个参数传入正则表达式,第二个参数传入要匹配的字符串。
输出结果是SRE_Match对象,该对象有个两个方法:group方法可以输出匹配的内容。span方法可以输出匹配的范围。
匹配目标
如果想从字符串中提取一部分内容,可以是使用()括号将想要提取的子字符串括起来。
示例
import recontent = 'Hello 1234567 World_This is a Regex Demo'result = re.match('^Hello\s(\d+)\sWorld', content)print(result)print(result.group())print(result.group(1))print(result.span())
运行结果
<_sre.SRE_Match object; span=(0, 19), match='Hello 1234567 World'>Hello 1234567 World1234567(0, 19)
group()输出完整的匹配结果,而group(1)匹配第一个被()包围的匹配结果。
通用匹配
为了减少匹配工作,可以使用 .* ,其中 . 可以匹配任意字符(除换行符),* 代表匹配前面的字符无限次,组合在一起就是匹配任意字符。
示例
import recontent = 'Hello 123 4567 World_This is a Regex Demo'result = re.match('^Hello.*Demo$', content)print(result)print(result.group())print(result.span())
运行结果
<_sre.sre_match>object; span=(Hello 123 4567 World_This is a Regex Demo(0, 41)
贪婪与非贪婪
使用通用匹配.*时,有时候匹配到的并不是想要的结果。
示例
import recontent = 'Hello 1234567 World_This is a Regex Demo'result = re.match('^He.*(\d+).*Demo$', content)print(result)print(result.group(1))
运行结果
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>7
在贪婪模式下.*会匹配尽可能多的字符,正则表达式中.*后面是\d+,也就是至少一个数字,并没有指定具体多少个数字,因此 .* 就尽可能匹配多的字符,这里就把123456匹配了,给\d+留下一个可满足条件的数字7。
这里只需要使用非贪婪模匹配就可以,非贪婪匹配的写法是.*?,多了一个?
示例
import recontent = 'Hello 1234567 World_This is a Regex Demo'result = re.match('^He.*?(\d+).*Demo$', content)print(result)print(result.group(1))
结果如下
<_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>1234567
非贪婪模式就是尽可能匹配少的字符,当匹配到Hello后面的空白字符时,再往后的字符就是数字了,而\d+恰好可以匹配,那么.*?就不再匹配,交给\d+去匹配后面的数字。
修饰符
正则表达式可以包含一些可选标志来控制匹配的模式。
示例
import recontent = '''Hello 1234567 World_Thisis a Regex Demo'''result = re.match('^He.*?(\d+).*?Demo$', content)print(result.group(1))
运行结果
AttributeError Traceback (most recent call last)input 5 ''' 6 result = re.match('^He.*?(\d+).*?Demo$', content)----> 7 print(result.group(1))AttributeError: 'NoneType' object has no attribute 'group'
运行直接报错,也就是说正则表达式没有匹配到这个字符串,返回结果为None,而又调用了group方法导致AttributeError。
因为匹配的是除换行符之外的任意字符,当遇到换行符时,.*?就不能匹配了,导致匹配失败。
这里只需要加一个修饰符re.S,即可修正这个错误
result = re.match('^He.*?(\d+).*?Demo$', content, re.S)
运行结果
1234567
修饰符描述
转义匹配
如果目标字符串里面包含. ,就需要用到转义匹配。
示例
import recontent = '(百度) www.baidu.com'result = re.match('\(百度 \) www\.baidu\.com', content)print(result)
当遇到用于正则匹配模式的特殊字符时,在前面加反斜线转义即可。