Day 15 正则表达式 re模块
1.正则表达式
1.正则表达式不是Python独有的,它是一门独立的技术,如果在python中使用,必须导入re模块,正则表达式用来筛选字符串中的特定内容,一般情况下遇到reg都是与正则有关系
2.如果匹配具体内容,可以直接西,不需要正则表达式
3.正则表达式一般由元字符与量词组成
4.元字符
元字符 | 匹配内容与注意事项 |
\d | digit 匹配所有数字 注[\d\D],[\W\w],[\s\S] 任意一组可以匹配任意字符 |
\w | word 匹配字母数字下划线 |
\s | space 匹配所有空格(包括空格,制表符回车) |
\D | 匹配非数字的所有字符 |
\W | 匹配所有非字母数字下划线的所有字符 |
\S | 匹配所有非空格的所有字符 |
\n | 匹配回车符 |
\t | 匹配制表符 |
\b | 匹配一个单词的结尾 |
. | 匹配除换行符以外的所有字符 |
^ | 匹配字符串的开始 ^与$合用会精准的限制匹配内容,中间写什么就只匹配什么 |
$ | 匹配字符串的结尾 |
| | 或 注:只会匹配或符号两边的其中一个,从左往右, 所以要把长的放在短的前面 |
[..] | 匹配字符组的字符 用[]来限定,一个字符组只针对一个字符,字符组里面的内容都是或的关系 可以[1-9] 但要注意里面数字必须是从小到大 |
() | 匹配括号内的表达式,表示一个组 |
[^...] | 匹配非字符组里字符的内容 ^在字符组里是取反的意思 |
5:量词. 必须跟在正则符号也就时元字符后面,并且量词只能限制它前面紧挨着他的表达式
量词 | 使用说明 |
* | 匹配0次或无穷大次 |
+ | 匹配1次或无穷大次 |
? | 匹配0次或1次 |
{n} | 指定匹配重复n次 |
{m,n} | 指定匹配重复 m-n 次 |
{m,} | 指定匹配重复m次到无穷大次 |
6.转义字符 当我们需要匹配的内容中就是需要匹配\n而不是匹配换行符时就需要对\n中的\转义 如"\\n" "\."(匹配.本身) 用\转义
7.贪婪匹配: 在满足匹配时,匹配尽可能长的字符串
8.惰性匹配: 在正则表达式量词后面加? 如 .*? .+? {m,n}? {n,}?
9. .*? 的用法 .*?x 意思就是取前面任意长度的字符直到遇到X停止
2.re模块: python中使用正则必须使用re模块
1. re.findall 语法 re.findall('正则表达式', '待匹配的字符串')
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.findall('\d',s) # 找出字符串中正则表达式全部内容,返回一个列表,列表中元素就时正则匹配到的结果 print(res) # ['1', '4', '1', '4', '5', '3', '5']
2. re.search 语法: re.search('正则表达式', '待匹配的字符串')
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.search('\d',s) # 只会依据正则查一次 只要查到了结果 就不会再往后查找 print(res) # 不会直接返回匹配到的结果,而返回一个对象 没匹配到返回None print(res.group()) # 1 必须用group 才能看到匹配到的结果 如果没匹配到会报错
3. re.match 语法: re.match('正则表达式', '待匹配的字符串')
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.match('\d',s) # 只会匹配字符串开头部分 print(res) # 不会直接返回匹配到的结果,而返回一个对象 没匹配到返回None print(res.group()) # 1 必须用group 才能看到匹配到的结果 如果没匹配到会报错
4. group 当使用re.search与re.match 时会返回一个对象.需要用group取值
5. re.split 语法: re.split('正则表达式', '待匹配的字符串',切割次数)
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.split('\d',s) # 以匹配到的结果对字符串进行分割 返回一个列表 print(res) # ['', 'hkj', 'h', '', 'v', 'gh', '', 'mbjkkjk']
6 .re.sub 语法: re.sub('正则表达式','新的内容' ,'待匹配的字符串',替换次数)
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.sub('\d','哈哈',s) # 将s中每一个能被匹配到的替换成哈哈 print(res) # 哈哈hkj哈哈h哈哈哈哈v哈哈gh哈哈哈哈mbjkkjk
7. re.subn 语法: re.subn('正则表达式','新的内容' ,'待匹配的字符串',替换次数)
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.subn('\d','哈哈',s) # 将s中每一个能被匹配到的替换成哈哈,返回一个元组,第二个元素是共替换的次数 print(res) # ('哈哈hkj哈哈h哈哈哈哈v哈哈gh哈哈哈哈mbjkkjk', 7)
8. re.compile 语法: re.compile('正则表达式') 将传入的正则表达式一次性编译,可以拿到任意地方运行.节省时间,提高开发效率
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.compile('[0-9]') print(re.findall(res,s)) # ['1', '4', '1', '4', '5', '3', '5']
9. re.finditer 语法: re.finditer('正则表达式', '待匹配的字符串') 返回一个存放匹配结果的迭代器 节省内存空间
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.compile('[0-9]') res1 = re.finditer(res,s) print(next(res1).group()) # 通过next得到一个对象,用group取值 print(next(res1).group()) print(next(res1).group()) print(next(res1).group()) print(next(res1).group()) print(next(res1).group()) print(next(res1).group()) # 当值取完继续去触发StopIteration异常
10 re模块中分组的使用:
(1) 按分组取
import re res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','130120122232422159') print(res.group()) print(res.group(0)) # 与group 等价 print(res.group(1)) # 第一个分组匹配到的内容 print(res.group(2)) # 第二哥分组匹配到的内容
(2) 起别名 在分组内使用 ?P<名字> 起别名,注意P大写, 注意用别名访问时别名需要加引号
import re res = re.search('^[1-9](?P<name>\d{14})(?P<pwd>\d{2}[0-9x])?$','130120122232422159') print(res.group()) print(res.group(0)) # 与group 等价 print(res.group(1)) # 第一个分组匹配到的内容 print(res.group(2)) # 第二哥分组匹配到的内容 print(res.group('name')) # name 匹配的内容 print(res.group('pwd')) # pwd 匹配的内容
(3) 使用re.findall 分组存在时,分组优先 在分组内使用?: 取消优先
import re ret1 = re.findall('www.(baidu|163).com', 'www.163.com') # 分组优先 print(ret1) # ['163'] ret2 = re.findall('www.(?:baidu|163).com', 'www.163.com') # 分组内使用?:取消分组优先 print(ret2) # ['www.163.com']
(4) 使用re.split 分组存在时不会将 匹配到内容丢掉
import re s = '1hkj4h14v5gh35mbjkkjk' res = re.split('(\d)',s) print(res) # ['', '1', 'hkj', '4', 'h', '1', '', '4', 'v', '5', 'gh', '3', '', '5', 'mbjkkjk']
3 爬虫案例.
import requests import re import json def getPage(url): response = requests.get(url) return response.text def parsePage(s): com = re.compile( '<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>' '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>', re.S) ret = com.finditer(s) for i in ret: yield { "id": i.group("id"), "title": i.group("title"), "rating_num": i.group("rating_num"), "comment_num": i.group("comment_num"), } def main(num): url = 'https://movie.douban.com/top250?start=%s&filter=' % num response_html = getPage(url) ret = parsePage(response_html) f = open("move_info7", "a", encoding="utf8") for obj in ret: print(obj) data = json.dumps(obj, ensure_ascii=False) f.write(data + "\n") if __name__ == '__main__': count = 0 for i in range(10): main(count) count += 25