0%

Python爬虫学习记录(一):正则表达式

正则表达式的使用

正则表达式的匹配规则网上都有,这里不放出来了,毕竟只是记录学习的博文。 以下讲几个一直没搞明白的点。

贪婪与非贪婪

实现介绍通用匹配,以.*表示。.代表匹配任意字符,*代表匹配0个或多个表达式所以两个连用就代表匹配任意字符。比如字符串'Hello Python and Anaconda',表达式为'^Hello.*Anaconda$'。代码如下:

1
2
3
4
5
import re

txt = 'Hello Python and Anaconda'
result = re.match("^Hello.*Anaconda$", txt)
print(result.group())
可以得出我们想要的结果,因为.*代表匹配任意个字符,所以该正则表达式会在Hello之后一直匹配成功,直到遇到Anaconda停止。其中.*其实就是贪婪匹配。但是有时候贪婪匹配会出很大的问题。比如字符串'My tel number is 15012345678',正则表达式为'^My.*(\d+)$'。具体代码如下:
1
2
3
4
5
6
import re

txt = 'My tel number is 15012345678'
result = re.match("^My.*(\d+)$", txt)
print(result.group())
print(result.group(1))
首先这段代码意思是获取字符串中的手机号码,(\d+)代表一个组,这个组里面匹配的东西就是我们需要的结果,而我们的代码也看起来很正常\d+就意味着匹配多个数字。可以看到这段代码print(result.group(1))就是输出手机号。但是结果却只匹配到了8,因为.*代表了贪婪匹配,它会尽可能的匹配到多的字符。因为.*代表匹配任意多的字符串,所以它看到1501234567会一直往下匹配,知道看到8,发现8已经是最后一个数字了,如果这个8不与\d+匹配岂不是出现系统漏洞了,因为\d+就是让你匹配数字,你不匹配不是违反了规则?所以匹配成功。最后将8加入组中,通过result.group(1)获取到这一组。所以贪婪匹配在这种情况是有问题,这就引出了非贪婪匹配:.*?。代码如下:
1
2
3
4
5
6
import re

txt = 'My tel number is 15012345678'
result = re.match("^My.*?(\d+)$", txt)
print(result.group())
print(result.group(1))
如果运行这段代码,就会发现匹配成功了。所以以后尽量使用非贪婪模式.*?,而不是贪婪模式.*

修饰符

代码

1
2
3
4
5
6
import re

txt = 'My tel number is 15012345678'
result = re.match("^My.*?(\d+)$", txt, re.S)
print(result.group())
print(result.group(1))
这里引用了上面的代码,注意多了个re.S,它代表使.匹配包括换行在内的所有字符。也就是说不加re.S,.其实是匹配不到换行符的。应用场景:网页代码中嵌套标签会经常出现这些换行符,要加入re.S。其他的方法re.search(),re.findall()用法类似。 待补充。。。

re模块中的方法

  1. match() 这方法从头开始匹配,如果一开始即第一个字符就不匹配,直接就算匹配失败。可以用于校验用户输入的信息是否合乎规范。
  2. search() 从头开始匹配,扫描整个字符串,如果碰到一段字符串匹配成功了就立即返回,它只会返回一个结果。
  3. findall() 跟它名字一样,扫描整个字符串,获得所有匹配成功的结果。
  4. 待补充。。。

举一个栗子

爬取牛客网的技术栈。