正则表达式

正则是用一些具有特殊含义的符号组合在一起来描述字符或者字符串的方法,这些特殊符号组合在一起称为正则表达式,正则说白了就是一种规则。

正则本质上是一种小型的编程语言,它内嵌在Python中并通过re模块实现

 

1.元字符

在正则表达式中一共有11个元字符: 

. ^ $ * + ? {} [] () \ |

1) . 代表除换行符之外的任意一个符号,(如果想代表换行符也有办法,就是在方法的参数中,更改模式为re.S)

2)^ 代表以什么开头

3) $ 代表以什么结尾,如果^ . $就表示从头匹配到尾,完全匹配

4) * + ? {}

这几个都表示重复,

*表示前面的字符重复零到无穷次

+表示前面的字符重复一到无穷次

? 表示前面的字符重复零或一次

{} 大括号里可以指定数字,表示重复多少次,或者指定一个范围,表示重复这个范围的次数

ret=re.findall('12{1,3}','12222222')
print(ret)  #['1222'] 默认贪婪匹配

5) 字符集[] 只匹配字符集中的一个符号,是或者的关系。

   需注意的是:元字符在字符集里并没有特殊功能

  在字符集中有功能的符号只有三个:- ^ \

  - 代表范围,0-9,a-z,A-Z

  ^ 写在字符集开头代表取反,‘非’的意思,注意非的是字符集中的所有字符

ret=re.findall('[^abc]','abdcdefg')
print(ret)  #['d', 'd', 'e', 'f', 'g']

  \代表转义

6) 管道符 | 也是或者的意思,与字符集的区别在于,管道符不止匹配一个

  如果A和B是正则表达式,A|B将匹配任何匹配了A或者B的字符串。| 的优先级非常低,是为了当你有多字符要选择时能适当的运行。举个例子来说明管道符与字符集的区别:

#如果要匹配Python和Jython
ret=re.findall('[PJ]ython','Python,Jython')
#但是如果要匹配python和perl呢
ret=re.findall('p(?:ython|erl)','python,perl')

 

7) 转义符 \ 

  1.转义符后边跟元字符去除特殊功能,如\.就表示匹配.

  2.抓义符后边跟一些普通字符实现特殊功能,如\d表示任意十进制数

  \d  匹配任何十进制数;      它相当于类 [0-9]。
  \D  匹配任何非数字字符;    它相当于类 [^0-9]。
  \s  匹配任何空白字符;      它相当于类 [ \t\n\r\f\v]。
  \S  匹配任何非空白字符;    它相当于类 [^ \t\n\r\f\v]。

  \w  匹配任何字母数字字符;   它相当于类 [a-zA-Z0-9_]。                    

  \W  匹配任何非字母数字字符; 它相当于类 [^a-zA-Z0-9_]
  \b  匹配一个特殊字符边界,比如空格 ,&,#等

  \A 匹配字符串开始

  \z 匹配字符串结束

  \Z 匹配字符串结束,如果存在换行,只匹配到换行前的结束字符

  \G 匹配最后匹配完成的位置

  \n 匹配一个换行符

  \t 匹配一个制表符  

 注意:当我们需要匹配\ 时需要在规则中写四个\,因为我们写的正则表达式,首先要由Python解释器先翻译,再由re模块解释,如果在规则外面加一个r,表示原生字符串,就跳过了Python解释器翻译的过程

8) 分组()表示把括号里的表达式当成一个整体处理

 在分组的时候可以为分组命名,称作有名分组

ret=re.search(r'(?P<first_mul>-?\d+\.?\d*)(?:\*|\/)(?P<second_mul>-?\d+\.?\d*)', s)

  在findall方法中,分组具有优先级,如果要取消优先级,就要在规则前加一个?:

ret=re.findall('p(ython|erl)','python,perl')
print(ret)  #['ython', 'erl']
ret=re.findall('p(?:ython|erl)','python,perl')
print(ret)  #['python', 'perl']

2.贪婪匹配

贪婪匹配是指在满足匹配条件时,匹配尽可能长的字符串,默认情况下就是贪婪匹配,. * + {} 默认情况下都是贪婪匹配

s='<div>zhang<img></div><a href=''></div>'
ret=re.findall('<div>.*</div>',s)
print(ret)      #['<div>zhang<img></div><a href=></div>']

非贪婪匹配的话要在非贪婪的规则后面加一个问号?

s='<div>zhang<img></div><a href=''></div>'
ret=re.findall('<div>.*?</div>',s)
print(ret)      #['<div>zhang<img></div>']

.*? 经常会在爬虫中应用到,.*?x就是匹配任意长度的字符,直到一个x出现

3.常用方法

1) re.fidall() 方法

  匹配所有满足条件的结果,并将结果放在列表中,没有匹配到的话返回空列表

ret=re.findall('[PJ]ython','Python,Jython')
print(ret)  #['Python', 'Jython']

 re.search() 方法

  只匹配到第一个满足条件的结果,并返回一个包含匹配结果的对象

  可以通过.group() 的方法得到匹配到的字符串,没有匹配到的话返回None

ret=re.search('[PJ]ython','Python,Jython')
print(ret.group())  #Python
ret=re.search('[ab]ython','Python,Jython')
print(ret)          #None
print(ret.group())  #报错AttributeError: 'NoneType' object has no attribute 'group'

  前面提过的有名分组,可以通过.group(组名) 的方式,只提取指定组名的信息

s='3*2'
ret=re.search(r'(?P<first_mul>-?\d+\.?\d*)(?:\*|\/)(?P<second_mul>-?\d+\.?\d*)', s)
print(ret.group('first_mul'))   #3
print(ret.group('second_mul'))  #2

    re.match() 方法

  和search方法差不多,不同处是match方法只在字符串开头的地方进行匹配

 re.split() 分割,与字符串中的分割方法只能指定一个确定的分割符不同,正则中的分割可以用正则表达式作为分隔符

s='hello124124world3235hi'
ret=re.split('\d+',s)
print(ret)  #['hello', 'world', 'hi']

还可以指定最大分割次数

s='hello124124world3235hi'
ret=re.split('\d+',s,1)
print(ret)  #['hello', 'world3235hi']

还可以显示分割符

s='hello124124world3235hi'
ret=re.split('(\d+)',s,1)
print(ret)  #['hello', '124124', 'world3235hi']

re.sub() 替换

ret=re.sub('w.{2,3}d','everyone','hello wasd')
print(ret)  #hello everyone

re.subn() 替换并返回替换次数

ret=re.subn('w.{2,3}d','everyone','hello wasd')
print(ret)  #('hello everyone', 1)

re.compile() 编译,就是把一个规则变成一个对象,如果频繁使用这个规则的话,就不用每次都在re里面写规则了

obj=re.compile('\d+')
ret=obj.findall('agasgagr4t24aga43')
print(ret)  #['4', '24', '43']

re.finditer() 返回的是一个迭代器对象,这个方法是为了处理那种如果返回的内容很多,都放在列表中会很占内存,这时就可以把匹配到的结果放到一个迭代器对象中,什么时候用,什么时候取

ret=re.finditer('\d+','asg67gas6gasd58gasg69asg58asg96g9as6ga78')
print(ret)  #<callable_iterator object at 0x000001D415E3B240>
print(next(ret).group())    #67
print(next(ret).group())    #6
print(next(ret).group())    #58

4.练习

爬取豆瓣top250网页上排行榜中电影的影片名,评分,评分人次以及简介

 1 import requests
 2 import re
 3 def getpage():
 4     respnse_str=requests.get('https://movie.douban.com/top250?start=0&filter=')
 5     return respnse_str.text
 6 def run():
 7     resonse=getpage()
 8     obj=re.compile('<div class="item">.*?<em.*?>(?P<id>\d+)</em>.*?<span class="title">'
 9                    '(?P<title>.*?)</span>.*?<span.*?>(?P<grade>\d+\.\d)</span>'
10                    '.*?<span>(?P<evalu>.*?)</span>.*?<span class="inq">(?P<intro>.*?)</span>',re.S)
11     ret=obj.findall(resonse)
12     with open('movie.ini','w')as f:
13         for i in ret:
14             print('')
15             for j in i:
16                 j+=' '
17                 print(j,end=' ')
18 run()
View Code

 

posted @ 2017-07-02 11:40  张璨  阅读(627)  评论(0编辑  收藏  举报