1.正则表达式简介
1.1 概念
正则表达式是对字符串操作的⼀种逻辑公式,就是⽤事先定义好的⼀些特定字 符、及这些特定字符的组合,组成⼀个“规则字符串”,这个“规则字符串”⽤来 表达对字符串的⼀种过滤逻辑
1.2 正则表达式的应用场景
- 表单验证(例如 : ⼿机号、邮箱、身份证…)
- 爬虫
2. 正则表达式对python的支持
2.1 普通字符
字⺟、数字、汉字、下划线、以及没有特殊定义的符号,都是"普通字符"。正则表达式中的普通字符,在匹配的时候只匹配与⾃身相同的⼀个字符。 例如:表达式c,在匹配字符串abcde时,匹配结果是:成功;匹配到的内容 是c;匹配到的位置开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语⾔的不同⽽可能不同。
match()函数
- match(pattern, string, flags=0) 第⼀个参数是正则表达式,如果匹配成功,则返回⼀个match对象,否则返 回⼀个None
- 第⼆个参数表示要匹配的字符串
- 第三个参数是标致位⽤于控制正则表达式的匹配⽅式 如: 是否区分⼤⼩写,多⾏匹配等等
2.2 元字符
正则表达式中使⽤了很多元字符,⽤来表示⼀些特殊的含义或功能
⼀些⽆法书写或者具有特殊功能的字符,采⽤在前⾯加斜杠""进⾏转义的⽅法。
例如下表所示
尚未列出的还有问号?、星号*和括号等其他的符号。所有正则表达式中具有特 殊含义的字符在匹配⾃身的时候,都要使⽤斜杠进⾏转义。这些转义字符的匹 配⽤法与普通字符类似,也是匹配与之相同的⼀个字符
2.3 预定义匹配字符集
正则表达式中的⼀些表示⽅法,可以同时匹配某个预定义字符集中的任意⼀个 字符。⽐如,表达式\d可以匹配任意⼀个数字。虽然可以匹配其中任意字符, 但是只能是⼀个,不是多个
2.4 重复匹配
前⾯的表达式,⽆论是只能匹配⼀种字符的表达式,还是可以匹配多种字符其 中任意⼀个的表达式,都只能匹配⼀次。但是有时候我们需要对某个字段进⾏ 重复匹配,例如⼿机号码13666666666,⼀般的新⼿可能会写成 \d\d\d\d\d\d\d\d\d\d\d(注意,这不是⼀个恰当的表达式),不但写着费 劲,看着也累,还不⼀定准确恰当。 这种情况可以使⽤表达式再加上修饰匹配次数的特殊符号{},不但重复书写表达 式就可以重复匹配。例如[abcd][abcd]可以写成[abcd]{2}
2.5 位置匹配和非贪婪匹配
位置匹配
有时候,我们对匹配出现的位置有要求,⽐如开头、结尾、单词之间等等
贪婪与非贪婪模式
在重复匹配时,正则表达式默认总是尽可能多的匹配,这被称为贪婪模式。例 如,针对⽂本dxxxdxxxd,表达式(d)(\w+)(d)中的\w+将匹配第⼀个d和最后⼀ 个d之间的所有字符xxxdxxx。可⻅,\w+在匹配的时候,总是尽可能多的匹配 符合它规则的字符。同理,带有?、*和{m,n}的重复匹配表达式都是尽可能地多
匹配校验数字的相关表达式:
特殊场景的表达式:
3.re模块常用方法
compile(pattern, flags=0)
这个⽅法是re模块的⼯⼚法,⽤于将字符串形式的正则表达式编译为Pattern模 式对象,可以实现更加效率的匹配。第⼆个参数flag是匹配模式 使⽤compile() 完成⼀次转换后,再次使⽤该匹配模式的时候就不能进⾏转换了。经过 compile()转换的正则表达式对象也能使⽤普通的re⽅法
flag匹配模式
search(pattern, string, flags=0)
在⽂本内查找,返回第⼀个匹配到的字符串。它的返回值类型和使⽤⽅法与 match()是⼀样的,唯⼀的区别就是查找的位置不⽤固定在⽂本的开头
findall(pattern, string, flags=0)
作为re模块的三⼤搜索函数之⼀,findall()和match()、search()的不同之处在 于,前两者都是单值匹配,找到⼀个就忽略后⾯,直接返回不再查找了。⽽ findall是全⽂查找,它的返回值是⼀个匹配到的字符串的列表。这个列表没有 group()⽅法,没有start、end、span,更不是⼀个匹配对象,仅仅是个列表! 如果⼀项都没有匹配到那么返回⼀个空列表
split(pattern, string, maxsplit=0, flags=0)
re模块的split()⽅法和字符串的split()⽅法很相似,都是利⽤特定的字符去分割 字符串。但是re模块的split()可以使⽤正则表达式,因此更灵活,更强⼤
split有个参数maxsplit,⽤于指定分割的次数
sub(pattern, repl, string, count=0, flags=0)
sub()⽅法类似字符串的replace()⽅法,⽤指定的内容替换匹配到的字符,可以 指定替换次数
4.分组功能
Python的re模块有⼀个分组功能。所谓的分组就是去已经匹配到的内容再筛选 出需要的内容,相当于⼆次过滤。实现分组靠圆括号(),⽽获取分组的内容靠的 是group()、groups(),其实前⾯我们已经展示过。re模块⾥的积个重要⽅法在 分组上,有不同的表现形式,需要区别对待
百度图片例子
import requests
import re
# 1 拿到目标url地址
url = 'https://image.baidu.com/search/flip?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1603269576905_R&pv=&ic=0&nc=1&z=&hd=&latest=©right=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1603269576907%5E00_1903X924&sid=&word=美女'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
}
# 2 拿到网页源码
r = requests.get(url,headers=headers)
ret = r.text
# print(ret)
# 3 拿到所有的图片url地址
result = re.findall('"objURL":"(.*?)"',ret)
# print(result)
# 4 保存图片
# a = 0
for i in result:
# 获取图片的名字
name = i.split('/')[-1]
# 处理图片的名字
# name = re.sub('/','',name)
print(name)
with open('img/'+name,'wb') as f:
# 网络问题通过异常进行处理
try:
r = requests.get(i)
except Exception as e:
print(e)
f.write(r.content)