1. 正则表达式
正则表达式(regularexpression)是一种描述字符串模式结构的方法,将模式(pattern)与字符序列(string)进行匹配,使用预定义的模式去匹配一类具有共同特征的字符串,如果符合规则的要求,就返回它。所谓模式也是一个字符串,它由一些普通字符和正则表达式元字符(metacharacters)组成,用于与字符串匹配,完成“查找和替换”之类的字符串处理任务。比如从字符串中找出有规律的手机号码、身份证号码、Email地址、URL网址等。
(1)模式定义
常见的正则表达式元字符及匹配示例见表

由于字符*、+、?等在正则表达式中有特殊的含义,因此它们不能用来匹配相应的普通字符。为了匹配有特殊含义的字符,必须使用转义序列“\”,比如:\.\?,就表示“.?”。除了作为转义序列符使用,还可以表示一些特殊序列,如下表所示:

(2)字符匹配
Python的re模块还为我们提供了多个函数用于匹配、搜索以及找出匹配对象和值,主要包括match( )、search( )和findall( )等:
match( ):从字符串开头去匹配并返回匹配的字符串的match对象,可以调用对象的group( )方法获取匹配成功的字符串;
search( ):并不局限于字符串的开头,扫描整个字符串找到匹配样式的第一个位置,并返回一个相应的匹配对象(match objects);
findall( ):以字符串列表或字符串元组列表的形式返回所有非重叠匹配。
(3)字符替换
除了利用正则表达式对字符串进行搜索外,也用于以各种方式修改字符串,如分割、替换等,主要提供的函数有:
split( ):将字符串拆分为一个列表,在正则匹配的任何地方将其拆分。
sub( ):找到正则匹配的所有子字符串,并用不同的字符串替换它们。
subn( ):与sub( )相同,但返回新字符串和替换次数。
2. 使用正则表达式解析数据
要解析豆瓣网爬取的数据,就要识别其查询结果网页的结构,仔细观察发现,与当当网不同,豆瓣网是用<div></div>标签对来表示查询结果的,每一个<div>就是一本图书。其网页的DOM结构如下图所示。

每一个本图书被装在一个“<div>……</div>”中,而我们需要提取的数据就包含在其中的子元素<div>里面,具体为“<divclass="title">”,该<div>包含的“<div>”包括了图书的作者、出版社等信息。也就是说,每本图书的信息包含在一个三层嵌套的<div>中。核心代码如下:
# 从HTML网页中提取所有CSS类型为content的div
pattern_str = r'<div class="content">\s*'+ \
r'<div class="title">.*?'+ \
r'<div class="rating-info">.*?</div>\s*</div>.*?</div>'
# re.S/re.DOTALL可以让“.”匹配换行符
pattn = re.compile(pattern_str, re.DOTALL)
for item in re.findall(pattn, self.search_book()):
book = Book()
# 从<a/>中直接提取图书名称
# ?控制只匹配0或1个,最小匹配、非贪婪的
# ( )提取整个字符串中符合括号里的正则的内容
book_pattn = r'<a.*?>(.*?)</a>'
book_info = re.findall(book_pattn, item)
# 只包含一个元素
book.title = book_info[0].strip()
# 提取作者/译者和出版社
book_pattn = r'<span class="subject-cast">(.+?)</span>'
……
匹配书名的正则表达式为“<a.*?>(.*?)</a>”,表示从一个超链接标签<a></a>中提起,提取的部分为圆括号部分“(.*?)”,表示非贪婪匹配。匹配作者和出版社等信息的正则表达式为“<span>(.+?)</span>”,包含在一对“<span>……</span>”中,通过“(.+?)”可以进行提取。