本文档原文来自:http://www.imooc.com/learn/550
正则表达式的概念
1. 使用单个字符串来描述匹配一系列符合某个语法规则的字符串;
2. 是对字符串操作的一种逻辑公式;
3. 应该场景:处理文本和数据;
4. 正则表达式的过程:依次拿出表达式和文本进行比较操作,如果每一个字符都匹配成功,则成功,否则匹配失败
python的第一个正则表达式
**import re**: Python正则表达式模块
re.compile(字符串模板)
pattern.match(被匹配的字符串)
字符串模板-->Pattern-->Match-->Result
import re
str = 'Hello python'
pa_1 = re.compile(r'Hello')#前面的r表示匹配模板的字符串是元字符串,这样就生成了一个pattern的实例
ma = pa_1.match(str)#ma是一个match对象
print ma_1.group()#返回匹配到的字符串
print ma_1.span()#返回被匹配字符串在原字符串的索引位置
pa_2 = re.compile(r'hello', re.I)#表示忽略大小写
ma = pa_2.match(str)#此时str字符串无论包含大写字符还是小写字符都会被匹配出来
注意点:
- 最好使用元字符串‘r’
- 最好生成一个pattern对象去match字符串
Python正则表达式的基本语法
- . 匹配任意字符(除了\n)
- […] 匹配字符集
>>> ma = re.match(r'[abc]', 'a')
>>> ma.group()
a
>>> ma = re.match(r'[abc]', 'd')
>>> ma
#结果显示为空,说明ma没有匹配到正确的结果
>>> ma = re.match(r'[a-z]', 'd')
>>> ma.group()
d #[a-z]表示匹配a-z的任何字符
>>> ma = re.match(r'[a-zA-Z]', 'A')
>>> ma.group()
A
>>> ma = re.match(r'[a-zA-Z0-9]', '9')
>>> ma.group()
9
- \d / \D 匹配数字/非数字
- \s / \S 匹配空白/非空白字符
- \w / \W 匹配单个字符[a-z A-Z 0-9] / 非单个字符
- * 匹配前一个字符0次或者无限次
>>> ma = re.match(r'[A-Z][a-z]', 'Aa')
Aa
>>> ma = re.match(r'[A-Z][a-z]', 'A')
>>> ma
#结果显示为空,说明ma没有匹配到正确的结果
>>> ma = re.match(r'[A-Z][a-z]*', 'A') #匹配字符集[a-z]的0个或者无限个字符
>>> ma.group()
A
>>> ma = re.match(r'[A-Z][a-z]*', 'Abcdefg') #匹配字符集[a-z]的0个或者无限个字符
>>> ma.group()
Abcdefg
>>>
- + 匹配前一个字符1次或者无限次
>>> ma = re.match(r'[_a-zA-Z]+[\w]*', '_http123') #表示匹配前一个字符集中的字符1次或者无限次,后一个字符集中的字符0次或者无限次
>>> ma.group()
_http123
- ? 匹配前一个字符0次或者1次
>>> ma = re.match(r'[1-9]?[0-9]', '90')
>>> ma.group()
90
>>> ma = re.match(r'[1-9]?[0-9]', '09')
>>> ma.group()
0
- {m} / {m,n} 匹配前一个字符m次或者m到n次
#可以用来匹配一个有效的邮箱
>>> ma = re.match(r'[a-zA-Z0-9]{6}', 'ABC123') #表示出现字符集中的字符必须6次
>>> ma.group()
abc123
>>> ma = re.match(r'[a-zA-Z0-9]{6}', 'ABC12')
>>> ma
#结果显示为空,说明ma没有匹配到正确的结果
>>> ma = re.match(r'[a-zA-Z0-9]{6}@qq.com', 'abc123@qq.com')
>>> ma.group()
abc123@qq.com
>>> ma = re.match(r'[a-zA-Z0-9]{6,10}@qq.com', 'abcd1234@qq.com') #出现字符集中的字符6到10次
>>> ma.group()
abcd1234@qq.com
- *? / +? / ?? 匹配模式为非贪婪模式(尽可能少匹配字符)
>>> ma = re.match(r'[0-9][a-z]*', '2ba')
>>> ma.group()
2ba
>>> ma = re.match(r'[0-9][a-z]*?', '2ba')
>>> ma.group()
2
- 边界匹配 ^ (匹配字符串的开头)$(匹配字符串的结尾)
#匹配一个邮箱
>>> ma = re.match('[\w]{4,10}@163.com', 'bobo@163.com')
>>> ma.group()
'bobo@163.com'
>>> ma = re.match('[\w]{4,10}@163.com', 'bobo@163.comabc')
>>> ma.group()
'bobo@163.com' #邮箱是不合法的,但是被匹配上了,这个并不是期望的结果
#匹配必须以@163.com结尾
>>> ma = re.match('[\w]{4,10}@163.com$', 'bobo@163.com')
- \A \Z 指定的字符串必须出现在开头或者结尾
ma = re.match('\Abobo[\w]*', 'bobopython')
- | 匹配或运算符左右的表达式
#匹配0-100的数字:0-99或100
>>> ma = re.match(r'[1-9]?\d$|100', '99')
>>> ma.group()
99
>>> ma = re.match(r'[1-9]?\d$|100', '100')
>>> ma.group()
100
- (ab) 括号中的表达式作为一个分组
#需要匹配163或者126的邮箱
>>> ma = re.match(r'[\w]{4,6}@(163|126).com', 'bobo@126.com')
\<数字> 引用编号为’数字’的分组所匹配到的字符串
(?P<名字>) 分组起一个别名
(?P=名字) 引用别名为’名字’的分组所匹配到的字符串
当存在多个引用的时候,使用别名的方式更加方便,可读性更强
re模块的其他方法
- search(pattern, string, flags = 0)
在一个字符串中查找匹配 - findall(pattern, string, flags = 0)
找到匹配,返回所有匹配部分的列表
>>> import re
>>> str1 = 'bobo videonum = 1000'
# 寻找字符串中的数字
>>> info = re.search(r'\d+', str1)
>>> info.group()
1000
>>> str2 = 'c++ = 100, java = 90, python = 80'
# 统计字符串中所有相关的数值
>>> info = re.search(r'\d+', str2)
>>> info.group()
100
#我们需要查找所有的数值,这个不是我们希望的结果
>>> info = re.findall(r'\d+', str2)
>>> info
['100','90', '80']
#求取列表中数字的和
>>> sum([int(x) for x in info])
270
- sub(pattern, repl, string, count=0, flags=0)
将字符串中匹配的正则表达式的部分替换成其他值
参数repl:
- 如果是字符串的时候可直接进行替换。
- 如果函数的话,sub()会先匹配string,然后把匹配到的内容返回给repl,然后由repl函数接收,并在函数中处理接收到的数据
str3 = 'bobo videonum = 1000'
>>> info = re.sub(r'\d+', '1001', str3)
>>> info
'bobo video = 1001'
#使用一次正则表达式数字部分+1
>>> def add1(match):
val = match.group()
# 强制转换成数字之后+1
num = int(val) + 1
return
>>> re.sub(r'\d+', add1, str3)
'bobo video = 1001'
- split(pattern, string, maxsplit=0, flags=0)
根据匹配分割字符串,返回分割字符串组成的列表
>>> str4 = 'class:C C++ Java Python'
# 分隔符包括冒号和空格
>>> re.split(r':| ', str4)
['class', 'C', 'C++', 'Java', 'Python']
# 分隔符包括冒号,空格和逗号
>>> str5 = 'class:C C++ Java Python,C#'
>>> re.split(r':| |,', str5)
['class', 'C', 'C++', 'Java', 'Python', 'C#']
利用正则表达式抓取网页内容
思路:
1. 抓取网页
2. 获取图片地址
3. 抓取图片内容并且保存到本地
>>> import urllib2
>>> import re
# 请求后台网站的网页
>>> req = urllib2.urlopen('http://www.imooc.com/course/list')
# 读取内容,缓存到buf中
>>> buf = req.read()
# 匹配以http开头和以jpg结尾的字符串所组成的图片地址
>>> listurl = re.findall(r'http:.+\.jpg', buf)
>>> i= 0
>>> for url in listurl:
f = open(str(i)+'.jpg', 'w')
req = urllib2.urlopen(url)
buf = req.read()
f.write(buf)
i += 1