正则表达式


1.正则表达式

正则表达式用来匹配一段字符串,如果字符串符合正则表达式的规则要求,就会被提取出来。

开源中国提供的正则表达式测试工具:https://tool.oschina.net/regex/#

2.match()

Python的re库提供了整个正则表达式的实现,一个常用的匹配方法是match()。

match()方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配,就返回 None。

代码:

import re

content = '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)
#\d后可以跟{4}代表匹配前面的规则4次
#第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串

print(result)
print(result.group())
print(result.span())

运行结果:输出

41
'Hello 123 4567 World_This'>
Hello 123 4567 World_This
(0, 25)

匹配目标

可以使用括号()将想提取的子字符串括起来,()实际上标记了一个子表达式的开始和结束位置,

被标记的每个子表达式会依次对应每一个分组,调用group()方法传入分组引索即可获取提取的结果

代码:

import re

content='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())

运行结果:输出

'Hello 1234567 World'>
Hello 1234567 World
1234567
(0, 19)

假如正则表达式后面还有其他(),可以依次用group(2)、group(3)来取。

通用匹配

. 点可以匹配任意字符, * 星代表匹配前面的字符无限次。

使用这些改写上面的正则表达式。

代码:

import re

content='Hello 123 4567 World_This is a Regex Demo'
result=re.match('^Hello.*Demo$',content)
print(result)
print(result.group())
print(result.span())

运行结果:输出

'Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41)

中间部分全部被忽略了。

贪婪与非贪婪

贪婪匹配下.*会匹配尽可能多的的字符。

非贪婪匹配下.*?会匹配尽可能少的字符。

如果非贪婪匹配在字符串结尾,可能会匹配不到任何内容。

所以在匹配时,在字符串中间尽可能使用非贪婪匹配。

修饰符

正则表达式可以包含一些可选标志修饰符来控制匹配模式。

如果在字符串中加入换行符。

代码:

import re

content='''Hello 123 4567 World_This
is a Regex Demo
'''
result=re.match('^He.*?(\d+).*?Demo$',content)
print(result.group(1))

运行结果会报错。

加一个修饰符re.S就可以修复这个错误。

result=re.match('^He.*?(\d+).*?Demo$',content,re.S)

re.S的作用是使 . 可以匹配换行符在内的所有字符,除此之外还有许多修饰符。

转义匹配

如果目标字符串包含 . , 可以在前面加反斜线转义即可。

代码:

import re

content='www.baidu.com'
result=re.match('www\.baidu\.com',content)
print(result)

运行结果:输出

'www.baidu.com'>

成功匹配所有字符串。

3.search()

match()是从开头匹配的,一旦开头不匹配,那么整个匹配就失败了,所以它更适合用来测试某个字符串是否符合某个正则表达式的规则。

search()方法在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果,如果搜索完了还没有找到,就返回None。

代码:

#coding:gbk
import re

html = ''''''
result=re.search('(.*?)',html,re.S)
if result:
    print(result.group(1),result.group(2))

运行结果:输出

齐秦  往事随风

4.findall()

findall()方法搜索整个字符串,获取匹配正则表达式的所有内容。

代码:

#coding:gbk
import re

html = ''''''
results=re.findall('(.*?)',html,re.S)
print(results)
print(type(results))
for result in results:
    print(result)
    print(result[0],result[1],result[2])

运行结果:输出

[('/2.mp3', '任贤齐', ' 沧海一声笑 '), ('/3.mp3', '齐秦', ' 往事随风 '), ('/4.mp3', 'beyond', ' 光辉岁月 '), ('/5.mp3', '陈慧琳', ' 记事本 '), ('/6.mp3', '邓丽君', ' 但愿人长久 ')]
<class 'list'>
('/2.mp3', '任贤齐', ' 沧海一声笑 ')
/2.mp3 任贤齐  沧海一声笑
('/3.mp3', '齐秦', ' 往事随风 ')
/3.mp3 齐秦  往事随风
('/4.mp3', 'beyond', ' 光辉岁月 ')
/4.mp3 beyond  光辉岁月
('/5.mp3', '陈慧琳', ' 记事本 ')
/5.mp3 陈慧琳  记事本
('/6.mp3', '邓丽君', ' 但愿人长久 ')
/6.mp3 邓丽君  但愿人长久

返回的列表中的每个元素都是元组类型。

5.sub()

sub()方法可以利用正则表达式来修改文本。

代码:

import re

content='4j559fbjfd9fsjb934jv'
content=re.sub('\d+','',content)
print(content)

运行结果:输出

jfbjfdfsjbjv

可以将其中的数字去除掉。

或者将文本中的a节点全部去掉。

代码:

#coding:gbk
import re

html = ''''''
html=re.sub('|','',html)
print(html)
result=re.findall('(.*?)',html,re.S)
for result in results:
    print(result.strip())

运行结果:输出

"songs-list">

class="title"> 经典老歌

class="introduction"> 经典老歌列表

    "list" class="list-group">
  • "2"> 一路上有你
  • "7"> 沧海一声笑
  • "4" class="active"> 往事随风
  • "6"> 光辉岁月
  • "5"> 记事本
  • "5"> 但愿人长久
Traceback (most recent call last): File "retest_8.py", line 27, in for result in results: NameError: name 'results' is not defined PS D:\spider> python retest_8.py
"songs-list">

class="title"> 经典老歌

class="introduction"> 经典老歌列表

    "list" class="list-group">
  • "2"> 一路上有你
  • "7"> 沧海一声笑
  • "4" class="active"> 往事随风
  • "6"> 光辉岁月
  • "5"> 记事本
  • "5"> 但愿人长久
一路上有你 沧海一声笑 往事随风 光辉岁月 记事本 但愿人长久

6.compile()

compile()方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用。

代码:

import re

content1='2016-12-15 12:00'
content2='2016-12-17 12:55'
content3='2016-12-22 13:21'
pattern=re.compile('\d{2}:\d{2}')
#将正则表达式编译成为一个正则表达式对象,以便复用

result1=re.sub(pattern, '', content1)
result2=re.sub(pattern, '', content2)
result3=re.sub(pattern, '', content3)
print(result1, result2, result3)

运行结果:输出

2016-12-15  2016-12-17  2016-12-22

compile()方法也可以传入修饰符,如re.S。

参考用书《python3网络爬虫开发实战》