python基础知识——正则表达式,

在学习Python的爬虫技术时,抓取到网页之后,需要从网页上复杂的代码中提取出目标字符串,那么怎样从成千上万的复杂代码中提取出自己想要的字符串呢?Python中提供了一种很好的方法:正则表达式。

所谓正则表达式:它是对字符串操作的一种逻辑公式,我们用事先定义的字符串定义一个“规则表达式”,用来对目标文件中的字符串进行过滤。

在Python中正则表达式需要的模块是“re”。

正则表达式的大致匹配过程是:
1.依次拿出表达式和文本中的字符比较,
2.如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。
3.如果表达式中有量词或边界,这个过程会稍微有一些不同。

最简单的一个示例:

 import re
 s='123abc456eabc789'
 re.findall(’abc’,s)

输出为:

['abc', 'abc']
其中findall是re 模块中最基本的一个函数,findall(rule,target,regulaton),第一个参数就是我们所指的规则表达式,第二个参数指的是目标字符串,第三个参数是匹配的规则(后面会有详细介绍)。这个函数会返回一个列表,列表中会存有所有匹配的字符串,如无,则返回一个空列表。

以上是个最简单的例子。当然实际中这么简单的用法几乎没有意义。为了实现复杂的规则查找,re规定了若干语法规则。它们分为这么几类:



着重介绍几个比较常用的:

1、贪婪与非贪婪模式

Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。

贪婪:‘*’  ,非贪婪:‘*?’   。例如:正则表达式 ”ab*” 如果用于查找 ”abbbc” 目标字符串,将找到”abbb”。而如果使用非贪婪的数量词”ab*?”,将找到”a”。

PS:我们一般选择使用非贪婪模式来提取。

2、反斜杠问题

与大多数编程语言相同,正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”\”,那么使用编程语言表示的正则表达式里将需要4个反斜杠”\\\\”:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\\”表示。同样,匹配一个数字的”\\d”可以写成r”\d”。有了原生字符串,妈妈也不用担心是不是漏写了反斜杠,写出来的表达式也更直观勒。


在主要介绍几个比较常用的re模块函数:

1、re.compile函数

这个函数的主要目的是为了防止findall函数的过多次使用带来的 时间效率降低问题(因为每一次都要把规则解释一遍,这个规则解释比较费时),利用compile函数,我们可以将规则预编译,使用编译过返回的Regular Expression Object或叫做Pattern对象来进行查找。

举个例子:

 s='111,222,aaa,bbb,ccc333,444ddd'
 rule=r’\b\d+\b’
compiled_rule=re.compile(rule)
compiled_rule.findall(s)


['111', '222']

使用了compile函数预定义了一个pattern对象,再调用这个对象的findall方法,就可以将规则的解释抽离出来,提高效率。


2、re. match与re.search函数
match( rule , targetString [,flag] )
search( rule , targetString [,flag] )
(注:re的match 与search函数同compile过的Pattern对象的match与search函数的参数是不一样的。Pattern对象的match与search函数更为强大,是真正最常用的函数)
按照规则在目标字符串中进行匹配。第一个参数是正则规则,第二个是目标字符串,第三个是选项(同findall函数的选项)
返回:若成功返回一个Match对象,失败无返回
findall虽然很直观,但是在进行更复杂的操作时,就有些力不从心了。此时更多的使用的是match和search函数。但它们的返回不是一个简单的字符串列表,而是一个MatchObject (如果匹配成功的话).。通过操作这个matchObject,我们可以得到更多的信息。需要注意的是,如果匹配不成功,它们则返回一个NoneType。所以在对匹配完的结果进行操作之前,你必需先判断一下是否匹配成功了,比如:

m=re.match( rule , target )
if m:                      #必需先判断是否成功
   doSomethin

这两个函数唯一的区别是:match从字符串的开头开始匹配,如果开头位置没有匹配成功,就算失败了;而search会跳过开头,继续向后寻找是否有匹配的字符串。针对不同的需要,可以灵活使用这两个函数。

例:
>>> s= 'Tom:9527 , Sharry:0003'
>>> m=re.match( r'(?P<name>\w+):(?P<num>\d+)' , s )
>>> m.group()
'Tom:9527'
>>> m.groups()
('Tom', '9527')
>>> m.group(‘name’)
'Tom'
>>> m.group(‘num’)
'9527'


3、编译后的Pattern对象

将一个正则式,使用compile函数编译,不仅是为了提高匹配的速度,同时还能使用一些附加的功能。编译后的结果生成一个Pattern对象,这个对象里面有很多函数,他们看起来和re模块的函数非常象,它同样有findall , match , search ,finditer , sub , subn , split 这些函数,只不过它们的参数有些小小的不同。一般说来,re模块函数的第一个参数,即正则规则不再需要了,应为规则就包含在Pattern对象中了,编译选项也不再需要了,因为已经被编译过了。因此re模块中函数的这两个参数的位置,就被后面的参数取代了。

findall , match , search 和finditer这几个函数的参数是一样的,除了少了规则和选项两个参数外,它们又加入了另外两个参数,它们是:查找开始位置和查找结束位置,也就是说,现在你可以指定查找的区间,除去你不感兴趣的区间。它们现在的参数形式是:

findall ( targetString [, startPos [,endPos] ] )
finditer ( targetString [, startPos [,endPos] ] )
match ( targetString [, startPos [,endPos] ] )
search ( targetString [, startPos [,endPos] ] )


这些函数的使用和re模块的同名函数使用完全一样。所以就不多介绍了。

除了和re模块的函数同样的函数外,Pattern对象还多了些东西,它们是:
flags 查询编译时的选项
pattern 查询编译时的规则
groupindex 规则里的组
这几个不是函数,而是一个值。它们提供你一些规则的信息。比如下面这个例子:

>>> p=re.compile( r'(?P<word>\b[a-z]+\b)|(?P<num>\b\d+\b)|(?P<id>\b[a-z_]+\w*\b)' , re.I )
>>> p.flags
2
>>> p.pattern
'(?P<word>\\b[a-z]+\\b)|(?P<num>\\b\\d+\\b)|(?P<id>\\b[a-z_]+\\w*\\b)'
>>> p.groupindex
{'num': 2, 'word': 1, 'id': 3}

我们来分析一下这个例子:这个正则式是匹配单词、或数字、或一个由字母或’_’开头,后面接字母或数字的一个ID。我们给这三种情况的规则都包入了一个命名组,分别命名为’word’ , ‘num’ 和 ‘id’。我们规定大小写不敏感,所以使用了编译选项(也就是匹配规则的一种) ‘I’,以后遇到re.I,就是指,大小写忽略不计,re.S,就是指多行查找。编译以后返回的对象为p,通过p.flag我们可以查看编译时的选项,不过它显示的不是’I’,而是一个数值2 。其实re.I是一个整数,2就是它的值。我们可以在python中查看一下:

>>> re.I
2
通过p.pattern可以查看被编译的规则是什么。使用print的话会更好看一些
>>> print p.pattern
(?P<word>\b[a-z]+\b)|(?P<num>\b\d+\b)|(?P<id>\b[a-z_]+\w*\b)

接下来的p.groupindex则是一个字典,它包含了规则中的所有命名组。字典的key是名字,values是组的序号。由于字典是以名字作为key,所以一个无命名的组不会出现在这里。

这就是对python正则表达式的简介了,在爬虫进阶的过程中肯定还会深入的学习,在这里就不献丑了~~




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MISAYAONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值