前言
继续昨天未完成的学习,然后上点强度
学习记录
正则表达式入门依旧是看小甲鱼的文档和白月黑羽up主的视频
切割字符串
字符串 对象的split
比如,从下面字符串中提取武将的名字
names = '关羽;张飞,赵云,马超,黄忠 李逵'
可以发现这些名字之间,有点是分号分隔,有的是逗号隔开,有的是空格隔开,而且分隔符号周围还有不定数量的空格
这时,可以使用正则表达式里的split函数
代码实现
import re
names = '关羽;张飞,赵云,马超,黄忠 李逵'
namelist = re.split(r'[;,\s]\s*',names)
print(namelist)
解读
- 使用正则表达式也并非一定要创建模式对象,然后调用它的匹配方法。因为re模块同时还提供了全局函数,例如match(),search(),findall(),sub(),split()等,这些函数第一个参数是正则表达式字符串,其他参数跟模式对象同名的方法采用一样的参数,返回值也一样。其实这些函数只是自动创建一个模式对象,并调用相关函数
- 如果程序大量使用正则表达式(例如在一个循环中使用),那么建议使用 先编译一个模式对象方法 ,因为预编译的话可以节省一些函数的调用
- \s也就是空白字符
运行结果
['关羽', '张飞', '赵云', '马超', '黄忠', '李逵']
字符串替换
匹配模式替换
字符串 对象的 replace方法只适用于 简单的 替换。有时,需要更加灵活的字符串替换。
比如,再下面这段文本中 所有的 链接中 找到所有的/avxxxxxx/ 这种以/av开头,后面接一串数字,这种模式的字符串
然后,将这些字符串全部替换为/cn345677/
names = '''
下面是这学期要学习的课程:
<a href='https://www.bilibili.com/video/av66771949/?p=1' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是牛顿第2运动定律
<a href='https://www.bilibili.com/video/av46349552/?p=125' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是毕达哥拉斯公式
<a href='https://www.bilibili.com/video/av90571967/?p=33' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是切割磁力线
'''
被替换的内容不是固定的,所以没法用 字符串的replace方法
这时,可以使用正则表达式里面的 sub 方法
import re
names = '''
下面是这学期要学习的课程:
<a href='https://www.bilibili.com/video/av66771949/?p=1' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是牛顿第2运动定律
<a href='https://www.bilibili.com/video/av46349552/?p=125' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是毕达哥拉斯公式
<a href='https://www.bilibili.com/video/av90571967/?p=33' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是切割磁力线
'''
newStr = re.sub(r'/av\d+?/', '/cn345677/' , names)
print(newStr)
- sub 方法也是替换字符串,但是被替换内容用 正则表达式字符串来表示 符号特征的所有字符串
- 第二个参数表示取代内容
- 第三个参数是 源字符串
指定替换函数
上面那个例子中,取代内容是一个固定字符串/cn345677/
那如果换个要求,将原来最后一个数字加6,比如/av66771949替换为/av66771955
这种较为复杂的替换,可以把 sub的第二个参数 指定为一个函数
import re
names = '''
下面是这学期要学习的课程:
<a href='https://www.bilibili.com/video/av66771949/?p=1' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是牛顿第2运动定律
<a href='https://www.bilibili.com/video/av46349552/?p=125' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是毕达哥拉斯公式
<a href='https://www.bilibili.com/video/av90571967/?p=33' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是切割磁力线
'''
# 替换函数,参数是 Match对象
def subFunc(match):
# Match对象 的 group(0) 返回的是整个匹配上的字符串,
src = match[0]
# Match对象 的 group(1) 返回的是第一个group分组的内容
number = int(match[1]) + 6
dest = f'/av{number}/'
print(f'{src} 替换为 {dest}')
# 返回值就是最终替换的字符串
return dest
newStr = re.sub(r'/av(\d+?)/', subFunc , names)
print(newStr)
获取组内字符串,如下
match.group(0) # 获取整个匹配字符串
match.group(1) # 获取第1个组内字符串
match.group(2) # 获取第2个组内字符串
Python 3.6 以后的版本 ,写法也可以更加简洁,直接像列表一样使用下标,如下
match[0]
match[1]
match[2]
上面这个例子中,正则表达式re.sub函数执行时, 每发现一个 匹配的子串,就会:
- 实例化一个 match对象,这个match对象包含了这次匹配的信息,比如:整个字符串是什么,匹配部分字符串是什么,里面的各个group分组字符串是什么
- 调用第2个参数,也就是调用回调函数subFunc,并且把刚才产生的match对象作为参数传递给subFunc
实践运用
问题
在吾爱曾经看到这样一个悬赏贴,如上图,命名位号码-名字,现在要求改成名字-号码,也就是改为陈芊芊-5642315589,需要批量处理,且最后要把jpg改为png,今天算是把正则表达式入门学习学完了,便想着实践下
素材获取
思路:先获取问题素材,在实践解决
首先生成50个姓名,单名和双名各25个,代码实现如下
import random
xing='赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜'
ming='豫章故郡洪都新府星分翼轸地接衡庐襟三江而带五湖'
namelist = []
for three in range(25):
X=random.choice(xing)
M="".join(random.choice(ming) for i in range(2))
namelist.append(X+M)
for two in range(25):
X=random.choice(xing)
M=''.join(random.choice(ming) for i in range(1))
namelist.append(X+M)
content = ' '.join(namelist)
with open('D:/PQ_img/name.txt','w') as f:
f.write(content)
运行结果如下
然后爬取50张图片,并以10位数字+.jpg形式命名(因为第一次爬取网页图片,纯纯新手,所以采用最简单易懂的形式爬取的)
实现代码
import requests
import re
import os
import random
# 需要爬取图片的网页地址
url = 'http://www.zhongyaocai360.com/'
# 得到网页源码
page = requests.get(url).text
# 用正则表达式过滤图片链接
p = re.compile(r'src="(http.+?.jpg)"')
# 在网页源码中找出图片地址
match = re.findall(p,page)
num = 1
dirs = 'D:/PQ_img'
# 如果不存在这个文件夹就创建这个文件夹
if not os.path.exists(dirs):
os.makedirs(dirs)
# 随机生成10位数的数字
seq = ''.join(str(i) for i in random.sample(range(10),10)) #sample(seq,n) 从序列seq中选择n个随机且独立的元素;
for i in match:
with open(f'{dirs}/{seq}.jpg','wb') as f:
f.write((requests.get(i)).content)
print(f'第{num}张图片下载完毕')
num += 1
seq = int(seq)+1
if num == 51:
break
运行结果如下
到这里发现已经偏离了主题,于是就想着将问题素材生成出来就可,以后在通过正则表达式真正实践
代码实现
import re
import os
fina_name = []
with open('D:/PQ_img/name.txt') as f:
content = f.read()
name = re.split(r'\s',content)
# 给列表中每个元素叫上一个字符-
namelist = ['-'+ i for i in name]
os.chdir('D:/PQ_img')
file_list = (os.listdir('D:/PQ_img'))
file_list.remove('name.txt')
# 删除列表中每个元素最后四个字符.jpg
f_l = [file_list[i][:-4] for i in range(50)]
# 将两个列表组合成元组
t = tuple(zip(f_l,namelist))
for i in range(50):
fina_name.append(t[i][0]+t[i][1])
# 给列表中每个元素加上一个字符串.png
new_name = [i + '.png' for i in fina_name]
old_name = (os.listdir('D:/PQ_img'))
old_name.remove('name.txt')
# 文件重命名
for i in range(50):
os.rename(old_name[i],new_name[i])
运行结果如下
小结
虽说最后的实践有点走偏了,但复习了之前所学,也运用了正则表达式,可惜不是正则表达式大量运用,不过也没关系,下次有机会在实践也是一样