正则表达式的常用符号:
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">¥<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)
运行结果如下: