正则表达式——re模块

2018-11-12  本文已影响0人  libdream

正则表达式的常用符号:

1 一般符号

.         匹配任意单个字符(不包括换行符\n),如a.b可以匹配的结果为abc、aic、a&c等

\         转义字符

[...]        字符集。对应字符集中的任意字符,如a[bcd],匹配的结果为ab、ac和ad

2 预定义字符集

\d                匹配一个数字字符,等价于[0-9]

\D                匹配一个非数字字符,等价于[^0-9]

\s                 匹配任何空白字符,包括空格、制表符、换行符等,等价于[\f\n\r\t\v]

\S                 匹配任何非空白字符,等价于[^\f\n\r\t\v]

\w                  匹配包括下划线的任何单词字符,等价于[A-Za-z0-9]

\W                 匹配任何非单词字符,等价于[^A-Za-z0-9]

3 数量词

*                    匹配前一个字符0或无限次

+                    匹配前一个字符1或无限次

?                  匹配前一个字符0或1次

{m}                 匹配前一个字符m次

{m,n}              匹配前一个字符m至n次

4 边界匹配

^                匹配字符串开头,如^abc匹配abc开头的字符串

$                匹配字符串结尾,如abc$匹配abc结尾的字符串

\A                仅匹配字符串开头,如\Aabc。

\Z                仅匹配字符串结尾,如abc\Z。

边界匹配在爬虫实战中使用较少,因为爬虫提取的数据大部分为标签中的数据,边界匹配在这里没有任何作用。

最后介绍爬虫实战中常用的(.*?),“()”表示括号的内容作为返回结果,“.*?”是非贪心算法,匹配任意的字符。例如,字符串"xxIxxddsgxxlovexxghhfgxxPythonxxsfsd",可以通过'xx(.*?)xx'匹配符合这种规则的字符串,代码如下:

import re

a = "xxIxxddsgxxlovexxghhfgxxPythonxxsfsd"

info = re.findall('xx(.*?)xx', a)

print(info)

运行结果如下:

re模块及其方法:

(1)search()函数

匹配并提取第一个符合规律的内容,返回一个正则表达式对象,语法如下:

re.search(pattern, string, flags=0)        

(2)sub()函数

用于替换字符串中的匹配项,语法如下:

re.sub(pattern, repl, string, count=0, flags=0)

sub()函数类似于字符串中的replace()函数,但sub()函数更加灵活。在爬虫实战中,sub()函数的使用也是极少的。

(3)findall()函数

匹配所有符合规律的内容,并以列表的形式返回结果。

在实战中,findall()函数的使用频率最多。以爬取北京地区短租房的价格为例,示例代码如下:

import re

import requests

r = requests.get('http://bj.xiaozhu.com/')

prices = re.findall('<span class="result_price">&#165;<i>(.*?)</i>',r.text)        #此处采用非贪婪匹配所有的字符,并返回结果列表

for price in prices:

    print(price)

运行结果如下:

re模块修饰符

re模块包含一些可选的标志修饰符,用来控制匹配的模式,如下:

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

re.L                做本地化识别(local-aware)匹配

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

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

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

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

在爬虫中,re.S是最常用的修饰符,它能够换行匹配。举个例子:

例如提取<div>指数</div>中的文字,可以通过以下代码实现:

import re

a = '<div>指数</div>'

word = re.findall('<div>(.*?)</div>', a)

print(word)

>>>['指数']

但,如果字符串是下面这样的多行字符串:

a = '''<div>指数

</div>'''

通过上面的代码则匹配不到div标签中的文字信息,结果如图。

这是因为findall()函数逐行匹配的,当第1行没有匹配到数据时,就会从第2行开始重新匹配,这样就没法匹配到div标签中的文字信息,这时便可通过re.S来进行跨行匹配

import re

a = '''<div>指数

</div>'''

word = re.findall('<div>(.*?)</div>', a, re.S)

print(word)

运行结果如下:

上一篇 下一篇

猜你喜欢

热点阅读