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)
浙公网安备 33010602011771号