http://blog.csdn.net/lxcnn/article/details/4268033

本文用的是python3.4,语法与python2.x有所不同,print后面要加括号,urllib->urllib.request:

python内嵌了正则表达式,在re模块中。

正则表达式的用途

1.测试字符串内的模式。(数据验证)

2.替换指定文本。

3.基于模式匹配从字符串中提取子字符串。

注意:

1.正则表达式模式被编译成一系列的字节码,然后由c编写的匹配引擎执行

2.并非所有的字符串处理都能用正则表达式完成

正则表达式的元字符

python的正则表达式前要加r的原因(当然也可以不加)

在Python的string前面加上‘r’, 是为了告诉编译器这个string是个raw string,不要转意backslash '\' 。 例如,\n 在raw string中,是两个字符,\和n, 而不会转意为换行符。由于正则表达式和 \ 会有冲突,因此,当一个字符串使用了正则表达式后,最好在前面加上'r'。

1. []

 -长用来指定一个字符集,在这个字符集中的一个可以拿来匹配:[abc]  [a-z]

-元字符在在字符集中不起作用

-在[]内用^表示补集,用来匹配不在区间范围内的字符

s=r'aba' 匹配abc
s=r't[io]p' 匹配tip或者top
s=r't[a-z0-9A-Z]'匹配t+0-9或者a-z或者A-Z

[abc]表示“a”或“b”或“c”
[0-9]表示0~9中任意一个数字,等价于[0123456789]
[\u4e00-\u9fa5]表示任意一个汉字
[^a1<]表示除“a”、“1”、“<”外的其它任意一个字符
[^a-z]表示除小写字母外的任意一个字符

import re
#定义正则
s=r'aba'
print(re.findall(s,"ababababa"))

2.^ ,$

^表示匹配开头,放在字符串的前面,$表示匹配结尾,放在字符串的尾部

s=r'^he' 匹配行首的he

s=r'boy$' 匹配行尾boy

s=r't[abc^]'  匹配ta或者tb或者tc或者t^, 这时^只是一个普通字符

s=r't[abc$]'  这时$也只是一个普通的字符

re.findall(r'^he','aa\nhe') 结果为空(一个串里面不算换行??)

re.findall(r'he$','2s'+'he') 得到he

print(re.findall(r'^abc','^abc')) 结果为空,此时^作为元字符处理

那么怎样匹配^abc呢?print(re.findall(r'\^abc','^abc'));

 

3. \

-反斜杠后面加不同的字符以表示不同特殊意义

 \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_]

-用于取消元字符: \[ 或者 \\等

一些不可见字符,或是在正则中具有特殊意义的元字符,如想匹配字符本身,需要用“\”对其进行转义。

如下所列字符

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

 

4.* , + ,?, {}

*作用是将前面的字符重复零到多次,最多20亿,0次就是没有

+ 表示将前面的字符重复一次到多次

? 表示将前面的字符重复零次到一次。 加在*或者+后面 表示最小匹配(默认是最大匹配)

{} {n},表示重复n次,{m,n} 表示重复m到n次, {m,} 表示至少重复m次

print(re.findall(r'ab+','abbbbbbb')) 最大匹配

print(re.findall(r'ab+?','abbbbbbb')) 最小匹配

s=r'^010-\d*8' 表示010-零个或多个数字并且以8结尾

s=r'^010-\d{8}$' 表示010-正好8个数字

如匹配电话号码要求以010为开头中间一个 - ,后面是8位数字

s=r'^010-\d\d\d\d\d\d\d\d'

s=r'^010-\d{8}' 花括号里面的数组表示重复次数,与上面等价

s=r'^010-?\d{8,10}$ 表示该串必须以010-开头,以8或9或10个数字结尾

print(re.findall(r'^010-?\d{8,10}','010-123456789012')) 最大匹配,末尾取到10个

print(re.findall(r'^010-?\d{8,10}?','010-123456789012')) 最小匹配,末尾取到8个

 

5. .小数点

匹配除了换行符号\n以外的任意字符

 

6.|

| 多个表达式之间取或的关系

当一个字符串的某一子串具有多种可能时,采用分支结构来匹配,“|”表示多个子表达式之间“或”的关系,“|”是以()限定范围的,如果在“|”的左右两侧没有()来限定范围,那么它的作用范围即为“|”左右两侧整体。

^aa|b$”在匹配“cccb”时,是可以匹配成功的,匹配的结果是“b”,因为这个表达式表示匹配“^aa”或“b$”,而“b$”在匹配“cccb ”时是可以匹配成功的。

^(aa|b)$”在区配“cccb”时,是匹配失败的,因为这个表达式表示在“开始”和“结束”位置之间只能是“aa”或“b”,而“cccb”显然是不满足的。

 

 

正则的编译

如果re的使用此时比较多,需呀进行正则的编译:

import re
r1=r'\d{3,4}-?\d{8}$'
print(re.findall(r1,'010-12345678'))
#编译后的匹配速度要快很多
phone_tel=re.compile(r1)
print(phone_tel.findall('010-12345678'))

 

r1=re.compile(r'\\seven')
print(r1.findall('\seven'))

如果不加r的话\s 还是会被转意!

正则的编译属性

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

IGNORECASE,I 使匹配对大小写不敏感

MULTILINE,M 多行匹配,影响^和$

VERBOSE,X 能够使用Res的verb。晰易懂

 例如:

re.findall(r'csvt.net','csvt\nnet',re.S) 得到匹配

re.findall(r'bb$','abb\naaabb\n',re.M) 得到两个匹配

不区分大小写:re.I

abcd_re=re.compile(r'[aA][bB][cC][dD]')
abcd_re2=re.compile(r'abcd',re.I)
print(abcd_re.findall('aBCd'))
print(abcd_re2.findall('AbCd'))

 

RE里面的方法:

match()  决定RE是否在字符串刚开始的位置

search()  扫描字符串,找到RE匹配的位置

findall()  找到RE匹配的所有子串,并作为一个列表返回

finditer()  找到RE匹配的所有子串,并把他们作为一个迭代器返回,用next()方法可以看到匹配到的对象

如果没有匹配到的话,match()和search()将返回None

如果成功的话就会返回一个MatchObject 实例

 

MatchObject实例的方法

group()  返回被RE匹配的字符串

start()   返回匹配开始的位置

end()   返回匹配结束的位置

span()  返回一个元祖包含匹配(开始,结束)的位置

 

实际程序中,最常见的做法是将MatchObject保存在一个变量里面,然后检查他是否为None

import re
p=re.compile(r'c..t')
m=p.match('fcsvt cfft pptcsst')
if m:
    print('Match found',m.group())
else:
    print('No match')

模块级函数

re模块提供了顶级函数调用,用re.来调用

match()匹配首部

search()匹配所有

sub() 匹配

subn() 匹配+匹配数目

split() 切割字符串

findall()匹配

 

正则的所有方法

>>> dir(re)

['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_alphanum_bytes', '_alphanum_str', '_cache', '_cache_repl', '_compile', '_compile_repl', '_expand', '_pattern_type', '_pickle', '_subx', 'compile', 'copyreg', 'error', 'escape', 'findall', 'finditer', 'fullmatch', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'sys', 'template']

>>> 

 

分组

用分组时会优先返回分组的数据 ,在做爬虫和网页分析时常用

email=r'\w+@\w+(\.com|\.cn)'
re.findall(email,'zjc@126.com') #返回.com

lang=r'src=(python|java)'
html=r'herf=(.+(\.com|\.cn))'
s='index src=python src=java herf=www.126.com'
print(re.findall(lang,s))#返回 python java
print(re.findall(html,s))#返回 www.126.com 和 .com

 

正则表达式应用

LRC歌词匹配

import re
f=open('b.lrc','r',encoding= 'utf-8')#支持中英文混合
str=f.read(-1)
f.close()
#p是严格要求,p2的要求比较宽泛
p=re.compile(r'\[\d{2}:\d{2}\.\d{2}\][^\[\]\n]+')
p2=re.compile(r'\[[^\[\]\n]+\][^\[\]\n]*')
lrcList=p2.findall(str)
for lrc in lrcList:
    print(lrc)

 小爬虫,下载百度贴吧的图片

import re
import urllib.request

def getHtml(url):
    fp = urllib.request.urlopen(url)
    html = fp.read()
    dehtml=html.decode('utf-8')
    fp.close()
    return dehtml

def getImg(html):
    reg = r"src=\"(http://imgsrc.baidu.com[^\"\n]+\.jpg)\""
    imgre = re.compile(reg)
    imglist = re.findall(imgre,html)
    return imglist

def download(imglist):
    x=0
    for imgurl in imglist:
        urllib.request.urlretrieve(imgurl,'%s.jpg'%x)
        x+=1

html=getHtml('http://tieba.baidu.com/p/3630331142')
imglist=getImg(html)
for img in imglist:print(img)
download(imglist)

 

posted on 2015-03-20 21:56  kylehz  阅读(276)  评论(0)    收藏  举报