正则表达式
正则表达式介绍
正则表达式是用来处理字符串的强大工具,有自己特定的语法结构。
可以使用正则表达式进行字符串的检索,替换,匹配验证
对于爬虫来说,使用正则表达式可以简化从HTML提取信息的步骤
匹配URL的正则表达式[a-zA-Z]+://[^\s]*
match
match 方法会尝试从字符串的起始位置开始匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配,就返回None。
实例如下:
def match_test():
import re
content = 'Hello 123 45678 World_This is a Regex Demo'
result = re.match('^Hello\s\d\d\d\s\d{5}\s\w{10}', content)
print(result) # 返回匹配的结果
print(result.group()) # 返回匹配到的内容
print(result.span()) # 匹配的范围, 匹配到的结果字符串在原字符串中的位置范围
实例执行的结果如下图所示

'^Hello\s\d\d\d\s\d{5}\s\w{10}':
^表示匹配字符串的开头
\d表示数字\d\d\d表示连续三个数字
\d{5}表示连续5个数字,这种方式更简单一些
\s表示一个空格
\w{10}表示匹配10个字母以及下划线。
匹配目标 group
使用match方法可以实现匹配,
如果从一段文本中提取出E-mail 地址或电话号码,
可以使用括号()将想要提取的字符串括起来。
() 实际上标记了一个子表达式的开始和结束文职,被标记的每个子表达式一次对应每个分组,调用group方法传入分组的索引即可获取提取结果。
实例如下:
实例中的\d+表示至少一个数字,至多不封顶
def match_test1():
import re
content = 'Hello 1234567 World_Test 45897546 is a regex demo'
result = re.match('^Hello\s(\d+)\sWorld_Test\s(\d+)', content)
print(result)
print('不带序号',result.group(), sep='\t')
print('序号为0',result.group(0),sep='\t')
print('序号为1', result.group(1),sep='\t')
print('序号为2', result.group(2),sep='\t')
实例运行的结果如下图所示
从运行的结果可以看出,不带序号与序号为0时输出的结果是一致的,都是匹配到的完整的字符串
想要提取的子字符串,其索引应当从1开始,而不是0

通用匹配 .*
前文的空白字符使用
\s,数字使用\d,这样写比较复杂
有一个万能匹配就是.*.可以匹配除了换行符之外的任意字符*表示前一个字符可以无限次
我们使用.*来进行匹配,实例代码如下
def match_test2():
import re
content = 'Hello 1234567 World_Test 45897546 is a regex demo'
result = re.match('^Hello.*is', content)
print(result)
print(result.group()) # 返回匹配到的内容
print(result.span()) # 匹配的范围, 匹配到的结果字符串在原字符串中的位置范围
匹配的结果如下图所示
贪婪匹配与非贪婪匹配
.*会匹配尽可能多的字符--------> 贪婪匹配
.*?会匹配尽可能少的字符-------> 非贪婪匹配
通过一个实例来对比贪婪匹配与非贪婪匹配的不同
实例目标:匹配目标字符串中的所有的数字
def match_test3():
import re
content = 'Hello 1234567 World_Test is a regex demo'
result1 = re.match('^Hello.*(\d+)', content) # 使用.* 来匹配 Hello后面的空格
result2 = re.match('^Hello.*?(\d+)', content) # 使用.*?来匹配 Hello后面的空格
result3 = re.match('^Hello.*?(\d+).*?', content) # 使用.*?匹配后面的字符串
result4 = re.match('^Hello.*?(\d+).*', content) # 使用.* 匹配后面的字符串
print('.*匹配空格:', result1.group(1))
print('.*?匹配空格:', result2.group(1))
print('.*?匹配尾字符串:', result3)
print('.*匹配尾字符串:', result4)
代码执行的结果如下图所示:

从代码运行的结果可以看出:
.*尽可能匹配更多的字符串,由于\d+至少有一个数字,就留下了一个数字7留给\d+进行匹配
.*?尽可能匹配更少的字符串, 由于\d+可以把所有的数字都匹配上,因此.*?就匹配上了一个空格
在进行字符串末尾匹配的时候,由于.*?尽可能少地匹配,因此就一个不匹配,就出现第三种结果
在进行字符串末尾匹配的时候,由于.*尽可能多地匹配,因此所有的字符都匹配上了,就出现了第四种结果
修饰符
如果一个字符串中存在换行符,那么在使用
.*或者.*?就匹配不上了
修饰符re.S可以使.*匹配包括换行符在内的所有字符。
实例代码如下:
def match_test4():
import re
content = '''Hello 1234567 World_Test
is a regex demo
'''
result = re.match('^Hello.*?(\d+).*', content, re.S)
print(result.group())
代码执行的结果如图所示
常见的修饰符
| 修饰符 | 描述 |
|---|---|
| re.I | 使匹配对大小写不敏感 |
| re.M | 多行匹配,影响^以及$ |
| re.S | 匹配包括换行符在内的所有字符 |
| re.U | 根据Unicode字符集解析字符。会影响\w, \W, \b, \B |
转义匹配
在使用
.*进行字符匹配的时候,如果目标字符串中本身就含有.怎么办?
只需要在用作正则匹配模式的特殊字符时,在此字符之前加\转义一下即可。
以匹配网址为例,实例如下:
def match_test5():
import re
content = '(百度) www.baidu.com'
result = re.match('\(百度\) www\.baidu\.com', content)
print(result)
代码执行的结果如下图所示
search
match方法是从自字符串的开头开始匹配的,如果开头不匹配,整个匹配就失败了。
因此match方法在使用时,需要考虑目标字符串开头的内容
更适合检测某个字符串是否符合某个正则表达式的规则
search方法在匹配时会扫描整个字符串,然后返回第一个匹配成功的结果。
在匹配时,search方法会依次以每个字符作为开头扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容
如果扫描完还没有找到符合规则的字符串,就返回None
search方法的用法与match方法类似。
需要注意的是,在对HTML文本进行匹配时,由于HTML文本包含换行符,因此需要加上re.S修饰符,以免出现匹配不到的问题
findall
search 方法获取得到的是与正则表达式相匹配的第一个字符串
如果想要获取与正则表达式相匹配的所有字符串,就需要用到findall方法。
sub
前面提到的match,search,findall三个方法都是通过正则表达式进行查找
使用sub可以通过正则表达式对字符串进行修改
例如将一个字符串中的数字换成空格,实例代码如下:
def sub_test():
import re
content = 'hijs2jjhj34bjhg6kj3kj7hg'
result = re.sub('\d+', ' ', content)
print(result)
代码执行的结果如下图所示
compile
这个方法可以将正则字符串变异成正则你倒是对象,以便在后面的匹配中复用
实例代码如下:
def compile_test():
import re
content1 = '2019-02-21 12:12'
content2 = '2019-02-24 12:17'
content3 = '2019-02-25 12:18'
content4 = '2019-02-26 12:19'
pattern = re.compile('\d{2}:\d{2}')
result1 = re.sub(pattern, '', content1)
result2 = re.sub(pattern, '', content2)
result3 = re.sub(pattern, '', content3)
result4 = re.sub(pattern, '', content4)
print(result1, result2, result3, result4)
代码运行的结果如图所示

本文介绍了正则表达式的基础知识,包括match方法用于从字符串起始位置匹配,group方法用于提取匹配内容,以及.*的贪婪和非贪婪匹配。还讨论了修饰符如re.S的作用,以及search、findall和sub方法在字符串查找和替换中的应用。最后提到了compile方法用于编译正则表达式以提高效率。




899

被折叠的 条评论
为什么被折叠?



