正则表达式及re模块
目录
正则表达式及re模块
正则表达式引入
案例:京东注册手机号校验
基本需求:手机号必须是11位、手机号必须以13 15 17 18 19开头、必须是纯数字
-
纯python代码实现
while True:
# 1.获取用户输入的手机号
phone_num = input('请输入您的手机号>>>>:').strip()
# 2.判断是不是11位
if phone_num == 11:
#.3.判断是不是纯数字
if phone_num.isdigit():
# 4.判断手机号的开头
if phone_num.startswith('13')or phone_num.startswith('15')or phone_num.startswith('17') or phone_num.startswith('18') or phone_num.startswith('18')
print('手机号码输入正确')
else:
print('手机号开头不符合')
else:
print('号码不是纯数字')
else:
print('手机号必须是11位')
2.python结合正则实现
import re
phone_num = input('请输入您的手机号>>>>:').strip()
if re.match('^(13|14|15|18)[0-9]{9}$', phone_num):
print('是合法的手机号码')
else:
print('不是合法的手机号码')
正则表达式是一门独立的技术,所有的编程语言都可以使用
它的作用可以简单的概括为:利用一些特殊的符号(也可以直接写需要查找的具体字符)的组合产生一些特殊的含义,然后去字符串中筛选出符合条件的数据
>>>>:筛选数据(匹配数据)
正则表达式概念
官方定义: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特殊字符、及这些特定字符的组合,组成一个‘规则字符串’,这个‘规则字符串’用来表达对字符串的过滤逻辑
正则表达式之字符串
字符组默认匹配方式是挨个挨个匹配
[0123456789] 匹配0到9任意一个数(全写)
[0-9] 匹配0到9任意一个数(缩写)
[a-z] 匹配26个小写英文字母
[A-Z] 匹配26个大写英文字母
[0-9a-zA-Z] 匹配数字或者小写字母或者大写字母,用来验证十六进制字符
ps:字符组内所有的数据默认都是或的关系
eg: 以[0-9]为例,我们尝试用几个待匹配字符串得到匹配结果
待匹配字符串 匹配结果 解释
'5' ['5'] [0-9]中有5,所以可以匹配到5
'o' ['None'] 字母不符合条件
'79i1' ['7','9','1'] 每个匹配到的结果 ,都会从字符串中切出
'11111' ['1','1','1','1','1'] 有几个1取几个1
正则表达式之特殊符号
重点记忆:
'''特殊符号默认匹配方式是挨个挨个匹配'''
| 元字符 | 匹配内容 |
|---|---|
| . | 匹配除换行符以外的任意字符 |
| \w | 匹配数字、字母、下划线 |
| \W | 匹配非数字、非字母、非下划线 |
| \d | 匹配数字 |
| ^ | 匹配字符串的开头 |
| $ | 匹配字符串的结尾 |
| 两者组合使用可以非常精确的限制匹配的内容 | |
| a|b | 匹配a或者b(管道符的意思是或) |
| () | 给正则表达式分组 不影响表达式的匹配功能 |
| [] | 字符组 内部填写的内容默认都是或的关系 |
| [^] | 取反操作 匹配除了字符组里面的其他所有字符 |
| 注意上尖号在中括号内和中括号意思完全不同 |
补充点:
| \s | 匹配任意的空白符 |
|---|---|
| \n | 匹配一个换行符 |
| \t | 匹配一个制表符 |
| \b | 匹配一个单词的结尾 |
| \D | 匹配非数字 |
| \S | 匹配非空白符 |
eg:
正则 待匹配字符串 结果 解释
\w 'ab-ab-a' ['a','b','a','b','a'] 匹配字符串中的所有字母\数字\下划线
\w\w 'ab-ab-a' ['ab,'ab'] 两个\w代表符合条件的两个字符连起来
[^a] 'ab-ab-a' ['b','-','b','-'] 一个[。。。] 仅表示匹配一个字符
正则表达式之量词
'''正则表达式默认情况下都是贪婪匹配>>>:尽可能多的匹配'''
| * | 匹配零次或多次 默认是多次(无穷次) |
|---|---|
| + | 匹配一次或多次 默认是多次(无穷次) |
| ? | 匹配零次或一次 作为量词意义不大主要用于非贪婪匹配 |
| 重复n次 | |
| 重复n次或更多次 默认是多次(无穷次) | |
| 重复n到m次 默认是m次 |
ps:量词必须结合表达式一起使用 不能单独出现 并且只影响左边第一个表达式
jason\d{3} 只影响\d
eg:
如正则表达式为[b],待匹配字符串为'bbbb'那么其匹配结果是['b','b','b','b']
而搭配量词,正则为[b],待匹配字符串为'bbbb',其匹配结果则为['bbbb']
b可以拿不到或者拿无数次,但是一旦是连着的b,都会被[b]全收**
课堂练习
*在线测试工具 https://tool.chinaz.com/regex/
正则表达式之贪婪与非贪婪匹配
""" 所有的量词都是贪婪匹配如果想要变为非贪婪匹配只需要在量词后面加问号"""
1.贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
2.加上? 会将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
eg:
待匹配的文本
<script>alert(123)</script>
1.待使用的正则(贪婪匹配)
<.*>
请问匹配的内容
<script>alert(123)</script> 一条
.* 属于典型的贪婪匹配,使用它,结束条件一般在左右明确指定
2.待使用的正则(非贪婪匹配)
<.*?>
请问匹配的内容
<script> </script>
几个常用的非贪婪匹配
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
转义符
"""斜杠与字母的组合有时候有特殊含义"""
\n 匹配的是换行符
\\n 匹配的是文本\n
\\\\n 匹配的是文本\\n
用\来取消\n的特殊含义
ps:如果是在python中使用 还可以在字符串前面加r取消转义
正则表达式之实战应用
1.编写校验用户身份证号的正则
^[1-9]\d{13,16}[0-9x]$
^[1-9]\d{14}(\d{2}[0-9x])?$
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
2.编写校验邮箱的正则
邮箱类型:
1、纯数字 123456@qq.com
2、纯字母 zhangsan@qq.com
3、字母数字混合 zhang123@qq.com
4、带点的 zhang.san@qq.com
5、带下划线 zhang_san@qq.com
6、带连接线 zhang-san@qq.com
正则表达式:
/^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$/g
3.编写校验用户手机号的正则(座机、移动)
4.编写校验用户qq号的正则
ps:能够写出简单的正则 能够大致看懂复杂的正则
python正则模块之re模块
在python中如果想要使用正则 可以考虑re模块
import re
# 1.匹配所有
res = re.findall('a','apple everyday amy')
print(res) # ['a', 'a', 'a'] 查找所有符合正则表达式要求的数据 结果直接是一个列表
# 2.匹配配所有返回迭代器
res = re.finditer('a','apple everyday amy')
print(res) # <callable_iterator object at 0x0000027BF6205B50> 查找所有符合正则表达式要求的数据 结果直接是一个迭代器对象
# 3.搜索到第一个
res = re.search('a','apple everyday amy')
print(res) # <re.Match object; span=(0, 1), match='a'>
print(res.group()) # a 匹配到一个符合条件的数据就立刻结束
# 4.只匹配开头
res = re.match('a','apple everyday amy')
print(res) # <re.Match object; span=(0, 1), match='a'>
res = re.match('a','pple everyday amy')
print(res) # None 匹配字符串的开头 如果不符合后面不用看了
print(res.group()) # 报错
# 5.正则模板
obj = re.compile('\d{3}') # # 当某一个正则表达式需要频繁使用的时候 我们可以做成模板
res1 = obj.findall('1233455768977')
res2 = obj.findall('bshjfkhjsgskbjsdnmbjjbbcn')
print(res1,res2) # ['123', '345', '576', '897'] []
# 6.其他方法
ret = re.split('[ab]','abcdc') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret) # ['', '', 'cdc']
ret = re.sub('\d', 'H', 'eva3jason4yuan4', 1) # 将数字替换成'H',参数1表示只替换1个
print(ret) # evaHjason4yuan4
ret = re.subn('\d', 'H', 'eva3jason4yuan4') # 将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret) # evaHjasonHyuanH
re模块补充说明
1.分组优先
# res = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
# print(res) # ['oldboy']
# findall分组优先展示:优先展示括号内正则表达式匹配到的内容
res = re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
print(res) # ['www.oldboy.com']
res= re.search('www.(baidu|oldboy).com','www.oldboy.com')
print(res.group()) # www.oldboy.com
res = re.match('www.(baidu|oldboy).com','www.oldboy.com')
print(res.group()) # ww.oldboy.com
取消分组展示,在括号前面添加 (?:\d)
2.分组别名
# 补充说明
import re
res = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(res) # ['oldboy']
# findall分组优先展示:优先展示括号内正则表达式匹配到的内容
res = re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
print(res) # ['www.oldboy.com']
res= re.search('www.(baidu|oldboy).com','www.oldboy.com')
print(res.group()) # www.oldboy.com
res = re.match('www.(baidu|oldboy).com','www.oldboy.com')
print(res.group()) # ww.oldboy.com
res = re.search('www.(?P<name>baidu|oldboy)(?P<haha>.com)','www.oldboy.com')
print(res.group()) # www.oldboy.com
print(res.group('name')) # oldboy
print(res.group(0)) # www.oldboy.com
print(res.group(1)) # oldboy
print(res.group(2)) # .com
print(res.group('haha')) # .com
网络爬虫简介
网络爬虫:通过编写代码模拟浏览器发送请求获取数据并按照自己指定的要求筛选出想要的数据
小练习:利用正则表达式筛选出红牛所有的分公司数据并打印或保存
公司名称:
公司地址:
公司邮编:
公司电话:
代码实现:
"""
网络爬虫没有我们现在接触的那么简单
有时候页面数据无法直接拷贝获取
有时候页面还存在防爬机制 弄得不好ip会被短暂拉黑
"""
1.直接拷贝页面数据到本地文件
2.读取文件内容当做字符串处理
3.编写正则筛选内容
import re
# 1.文件操作
with open(r'demo.html','r',encoding='utf8') as f:
# 2.直接读取全部内容,无序优化
data = f.read()
# 3研究部分数据的特征,编写相应的正则表达式
"""
思路1:一次性获取每个分公司的数据
思路2:分部分挨个获取最后统一整合
"""
# res = re.findall("<h2>(.*?)</h2><p class='mapIco'>(.*?)</p><p class='mailIco'>(.*?)</p><p class='telIco'>(.*?)</p>",data)
# print(res) # [(),(),(),()]
comp_title_list = re.findall('<h2>(.*?)</h2>',data)
print(comp_title_list)
comp_address_list =re.findall("<p class='mapIco'>(.*?)</p>",data)
print(comp_address_list)
comp_email_list = re.findall("<p class='mailIco'>(.*?)</p>",data)
print(comp_email_list)
comp_phone_list = re.findall("<p class='telIco'>(.*?)</p>",data)
print(comp_phone_list)
res = zip(comp_title_list,comp_address_list,comp_email_list,comp_phone_list)
# print(list(res))
with open(r'comp_info.txt','w',encoding='utf8') as f:
for data_tuple in res:
print("""
公司名称:%s
公司地址:%s
公司邮箱:%s
公司电话:%s
""" % data_tuple)
f.write(
""" 公司名称:%s
公司地址:%s
公司邮箱:%s
公司电话:%s
""" % data_tuple
)

浙公网安备 33010602011771号