python3网络爬虫学习——正则表达式

正则表达式是处理字符串的强大工具,有着自己的语法结构。

1.实例引入

可以使用开源中国的 http://tool.oschina.net/regex# 可以看到有许多匹配项,正则表达式匹配就是按照一定规则将特定的文本提取出来。比如电子邮件开头是一段字符串,然后是一个@符号,最后是某个域名,这是由特定的格式组成的。至于匹配的具体规则,可以参见这个博客https://www.jianshu.com/p/773c32dcd254     一些规则的汇总可以看这个博主https://www.cnblogs.com/arcserver/p/6681914.html

 

 

2.match()

这里介绍一下常用的匹配方法——match(),向他传入要匹配的字符串以及正则表达式,就可以检测这个正则表达式是否匹配字符串。当然在requests库里使用正则表达式有关的函数和库都需要引用re模块。

match()方法中第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串。

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)
print(result)
print(result.group())
print(result.span())

运行结果如下

41
<_sre.SRE_Match object; span=(0, 25), match='hello 123 4567 world_this'>
hello 123 4567 world_this
(0, 25)

开头的 ^ 是表示匹配字符串的开头,也就是以hello开头,\s表示匹配空白字符串,\d表示匹配数字,\d{4}则表示匹配四个连续的数字,\w表示匹配数字,字母或下划线,同理\w{10}表示连续的十个字母

打印结果输出表示为SRE_Match类型数据表示匹配成功,该类型有两个属性,其中一个span表示输出匹配的范围,匹配到的字符在原字符串中的位置范围,这里显示为0到25

  •  匹配目标
import re
content = 'hello 1234567 world_this is a regex demo'
print(len(content))
result = re.match('^hello\s(\d+)\sworld',content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())



 40
 <_sre.SRE_Match object; span=(0, 19), match='hello 1234567 world'>
 hello 1234567 world
 1234567
 (0, 19)

如果想从字符串中提取出特定目标,比如一串数字,那么可以使用符号(),比如上述代码,使用了一个(),其表示了子表达式开始和结束的位置,然后使用group(1),这个与group()不同,前者会找出第一个被括号包起来的匹配结果,而后者则会输出所有匹配结果。

  • 通用匹配

向上述那样匹配需要的工作量太大了,因此我们为了简便,,可以通通使用  .(点)来匹配任何字符,用*(星)代表匹配前面的字符无限次,用XX$来表示以XX结尾的字符串,比如改为:

result = re.match('^hello.*Demo$',content)可以匹配整个content

  • 贪婪与非贪婪

有时候使用.*表示时,可能不会出现我们需要的结果,这就涉及到他的贪婪和非贪婪机制,上实例

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

 40
 <_sre.SRE_Match object; span=(0, 40), match='Hello 1234567 World_This is a Regex Demo'>
 7

结果为7却不是1234567,是因为d+表示的是后面的数字但并未表示多少位,而.*有一个机制,就是尽可能多的匹配字符,那么就会导致他只留了7给d+,那么作为贪婪机制的他,也有一个非贪婪机制的,那就是.*?  他会尽可能的少匹配字符,如果将上述He后的字符改为.*?那么就会匹配尽可能少的字符,就会把1234567留给d+

虽然这样不错,但有时候匹配结果在结尾的时候,非贪婪匹配可能就不会匹配到任何内容了比如

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



40
<_sre.SRE_Match object; span=(0, 35), match='Hello 1234567 World_This is a Regex'>
7

还有需注意的是只有最末尾的字符才可以使用XXX$结尾

  • 修饰符

上述的案例中我们如果加入了换行符,那么结果却会报错,系统显示匹配不到,系统返回None,真是因为.*匹配的都是除换行符外的任意字符,因此需要在其中加入一个修饰符,使系统可以辨识出换行符,下面上实例:

import re
content = '''Hello 1234567 Worl
d_This is a Regex Demo'''
print(len(content))
result = re.match('^He.*(\d+).*Regex.*?',content,re.S)
print(result)
print(result.group(1))

这样得到的结果和上述一样,注意的就是换行后单点号变成三个点,不然系统会识别不了,以下列出一些常见的修饰符

re.I       使匹配对大小写不敏感   

re.L         做本地化识别匹配

re.M        多行匹配,影响^和$

re.S        使 . 匹配包括换行在内的所有字符

re.U      根据Unicode字符集解析字符。这个标志影响\w, \W  \b  \8

re.X      该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

  •  转义匹配

如果我们想要匹配的字符就包括目标字符.*之类的咋办,可以利用转义字符。示例如下:

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


<_sre.SRE_Match object; span=(0, 17), match='(百度)www.baidu.com'>

 

 

3.search()

 使用search方法会扫描整个字符串,并返回匹配到字符串的第一个内容,而上述的match方法只会从最初始的字符串开始找起。

4.findall()

该方法会搜索整个字符串,然后返回匹配正则表达式的所有内容,会返回一个列表类型。

5.sub()

有时除了需要提取正则表达式外,还需要对其进行修改,因此可以用该函数,他的API为:

re.sub(‘要匹配的字符串’,‘’要换成的字符串‘,原字符串)

比如所有的数字去掉的话,那么第一个参数应该为'\d+',第二个参数为' ' 空白,第三个参数就直接为要替换的变量名,比如上述中的content。

6.compile()

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

import re
pattern = re.compile('[a-zA-Z]')
result = pattern.findall('as3SiOPdj#@23awe')
print (result)


['a', 's', 'S', 'i', 'O', 'P', 'd', 'j', 'a', 'w', 'e']

同时compile还可以传入修饰符,这样在search(),findall()中就不需要额外传了,因此其相当于是给正则表达式进行了一个封装。

 

posted @ 2018-08-23 20:50  gausstu  阅读(562)  评论(0)    收藏  举报