(七)常用模块----(一)
目录
7.1正则表达式
正则表达式:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑
在线正则表达式测试:http://tool.chinaz.com/regex/
a.普通字符
正则表达式 | 输入 | 输出 | 分析 |
[0-9] | 1 | ture | 范围是0-9 |
[0-9] | a | false | 没有a |
[a-z] | a | true | 小写字母 |
[A-Z] | A | false | 大写字母 |
[0-9a-z] | a | true | 范围括号内条件 |
b.特定字符
\d | 匹配数字 |
\D | 匹配非数字 |
\b | 匹配一个单词的结尾 |
\w | 匹配字母或数字或下划线 |
\W | 匹配非字母或数字或下划线 |
\s | 匹配任意的空白符 |
\S | 匹配非空白符 |
. | 匹配除换行符以外的任意字符 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结尾 |
a|b | 匹配字符a或字符b |
() | 匹配括号内的表达式,也表示一个组 |
[...] | 匹配字符组中的字符 |
[^...] | 匹配除了字符组中字符的所有字符 |
c.限定符(量词)
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 |
通过在 *,+或?限定符之后放置 ?,表达式从"贪心"表达式转换为"非贪心"表达式或者最小匹配
小+? | 小一小二小三 | 小 小 小 | 非贪心 |
小.+ | 小一小二小三 | 小一 小二 小三 | 贪心 |
小.{1,2} | 小一小二小三 | 小一小 小三 | 贪心 |
<.*> | <script>...<script> | <script>...<script> | 贪心 |
<.*?> | <script>...<script> | <script> <script> | 非贪心 |
.*?x | axabx | ax abx | 就是取前面任意长度的字符,直到一个x出现 |
分组 ()与 或 |[^]:
正则 | 输入 | 输出 |
[a-d][1-4] | a1b2 | a1 b2 |
([a-d][1-4])* | a1b2 | a1b2 |
身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部都是数字组成,首位不能为0;
如果是18位,则前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:
正则 | 待匹配字符 | 匹配 结果 | 说明 |
^[1-9]\d{13,16}[0-9x]$ | 110101198001017032 | 110101198001017032 | 首部是1-9,中间是{13,16}数字,结尾是[0-9x] |
^[1-9]\d{13,16}[0-9x]$ | 12345678912345x | 12345678912345x | |
^[1-9]\d{14}(\d{2}[0-9x])?$ | 12345678912345x | False | |
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ | 110105199812067023 | 110105199812067023 | |
转义符 \:
在python中,如果匹配一次"\n,只需要写成r'\n'即可。
字符集[][^]:
正则 | 待匹配字符 | 匹配 结果 | 说明 |
李[一小二大大三]* | 李一和李小二和李大大三 | 李一 | |
李[^和]* | 李一和李小二和李大大三 | 李一 | |
[\d] | 456bdha3 | 4 | |
[\d]+ | 456bdha3 | 456 | |
7.2re模块
findall()
import re
ret = re.findall('a', 'ab abc dsc') # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : ['a', 'a']
search():扫描整个字符串
ret = re.search('a', 'aca abc').group()
print(ret) #结果 : 'a'
// 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
// 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
content = 'Hello 123456789 Word_This is just a test 666 Test'
result = re.search('(\d+).*?(\d+).*', content)
print(result)
print(result.group()) // print(result.group(0)) 同样效果字符串
print(result.groups())
print(result.group(1))
print(result.group(2))
'''
<_sre.SRE_Match object; span=(6, 49), match='123456789 Word_This is just a test 666 Test'>
123456789 Word_This is just a test 666 Test
('123456789', '666')
123456789
666
'''
match():从首部开始匹配,有就结束
ret = re.match('a', 'abc')
print(ret)
//<re.Match object; span=(0, 1), match='a'>
//span:匹配开始到结束的范围
ret = re.match('a', 'abc').group()
print(ret)
//结果 : 'a'
group(0):有匹配,返回整体
split()
//str.split
s = 'abcd'
ret = s.split('a')
print(ret)
// ['','bcd']
//ret.split
ret = re.split('[ab]', 'abcd') // 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)
// ['', '', 'cd']
sub(),subn():替换
replace的使用范围局限性更小
ret = re.sub('\d', 'H', 'qwr23yui2tyu', 1) //将数字替换成'H',参数1表示只替换1个
print(ret) //qwrH3yui2tyu
ret = re.subn('\d', 'H', 'qwr23yui2tyu') //将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret) //('qwrHHyuiHtyu', 3)
compilel() 需要多次使用同一正则表达式
obj = re.compile('\d{3}') //匹配三个数字
ret = obj.search('abc123eeee') //正则表达式对象调用search,参数为待匹配的字符串
print(ret.group()) //结果 : 123
findter()
import re
ret = re.finditer('\d', 'ds3sy4784a') //finditer返回一个存放匹配结果的迭代器
print(ret) // <callable_iterator object at 0x10195f940>
print(next(ret).group()) // 查看第一个结果
print(next(ret).group()) // 查看第二个结果
print([i.group() for i in ret]) // 查看剩余的左右结果
优先级问题:findall(),split()
import re
ret = re.findall('www.(baidu|qq).com', 'www.baidu.com')
print(ret) // ['baidu'] //findall会优先把匹配结果组里内容返回
ret = re.findall('www.(?:baidu|qq).com', 'www.baidu.com')
print(ret) // ['www.baidu.com'] //取消优先级直需要加上?:
ret=re.split("\d+","aa1bb2cc")
print(ret) //结果 : ['aa', 'bb', 'cc']
ret=re.split("(\d+)","aa1bb2cc")
print(ret) //结果 : ['aa', '1', 'bb', '2', 'cc']
//没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
练习题:1、匹配标签
2、匹配整数
3、数字匹配
4、爬虫练习