正则匹配
正则匹配
正则表达式前戏
所有编程语言都支持正则匹配
案例:京东注册手机号校验
基本需求:手机号必须11位,手机号已13 15 17 18 19 开头、必须是纯数字
"""纯python代码实现"""
phone_num = input('请输入手机号').strip()
if len(phone_num) == 11:
# print('手机号必须是11位')
if phone_num.isdecimal():
# print('必须是纯数字')
if phone_num.startswith(('13', '15', '17', '18', '19')):
print('正确手机号')
else:
print('手机号开头不正确')
else:
print('手机号必须是纯数字')
else:
print('手机号必须是11位')
"""python结合正则实现"""
import re
data = input('请输入手机号').strip()
res = re.findall('^13|14|15|18[0-9]{9}$', data)
print(res)
if res:
print('正确手机号')
else:
print('手机号不正确')
字符组
"""字符组默认匹配方式是挨个挨个匹配"""
[0123456789] 匹配0到9任意一个数(全写)
[0-9] 匹配0到9任意一个数(缩写)
[a-z] 匹配26个小写英文字母
[A-Z] 匹配26个大写英文字母
[0-9a-zA-Z] 匹配数字或小写字母或大写字母
ps:字符组内所有的数据默认都是或的关系
特殊符号
"""特殊符号默认匹配方式是挨个挨个匹配"""
. 匹配除换行符以外的任意字符
\w 匹配数字,字母,下划线
\W 匹配非数字,非字母,下划线
\d 匹配数字
\D 匹配非数字
\s 匹配任意的空白符
\S 匹配非空白字符
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结尾
两者组合使用可以非常精确的限制匹配的内容
a|b 匹配字符a或字符b
() 匹配括号内的表达式,也表示一个组,不影响表达式的匹配功能
[] 匹配字符组中的字符,字符组 内部填写的内容默认都是或的关系
[^] 匹配除了字符组中的所有字符
量词
"""正则表达式默认情况下都是贪婪匹配》》》尽可能多的匹配"""
* 重复零次或更多次 默认是多次(无穷次)
+ 匹配一次或多次 默认是多次(无穷次)
? 匹配零次或一次 作为量次意义不大主要用于非贪婪匹配
{n} 重复n次
{n,} 重复n次或更多次 默认是多次(无穷次)
{n,m} 重复n道m次 默认是m次
ps:量词必须结合表达式一起使用 不能单独出现 并且只影响左边第一个表达式
jason\d{3} 只影响\d
小练习
正则 待匹配字符 匹配结果 说明
海. 海燕海娇海东 海燕海娇海东 匹配所有"海."的字符
^海. 海燕海娇海东 海燕 只从开头匹配"海."
海.$ 海燕海娇海东 海东 只匹配结尾的"海.$"
贪婪匹配与非贪婪匹配
"""所有的量词都是贪婪匹配如果想要变为非贪婪匹配只需要在量词后面加问号"""
待匹配的文本
<script>alert(123)</script>
待使用的正则(贪婪匹配)
<.*>
匹配内容
<script>alert(123)</script> 一条
#.*属于典型的贪婪匹配 使用他 结算条件一般在左右明确指定
待使用的正则(非贪婪匹配)
<.*?>
匹配内容
<script> </script> 两条
转义符
"""斜杠与字母的组合有时候有特殊含义"""
\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.编写校验邮箱的正则
3.编写校验用户手机号的正则(座机、移动)
4.编写校验用户qq号的正则
'''很多时候 很多问题 前人已经弄好了 你只需要花点时间找一找就可以'''
ps:能够写出简单的正则 能够大致看懂复杂的正则
re模块(正则模块)
在python中如果想要使用正则 可以考虑re模块
import re
常见操作方法
res = re.findall('a','jason apple eva')
print(res) # 查找所有符合正则表达式要求的数据 结果是一个列表
res = re.finditer('a','jason apple eva')
print(res) # 查找所有符合正则表达式要求的数据 结果直接是一个迭代器对象
res = re.search('a','jason apple eva')
print(res) # <re.Match object; span=(1, 2), match='a'>
print(res.group()) # a 匹配到一个符合条件的数据就立刻结束
res = re.match('a','jason apple eva')
print(res) # None 匹配字符串的开头 如果不符合后面不用看了
print(res.group()) # 匹配开头符合条件的数据 一个就结束
obj = re.complie('\d{3}') # 当某一个正则表达式需要频繁使用时候 我们可以做成模板
res1 = obj.findall('123123123123')
res2 = obj.findall('13123asd123123')
print(res1,res2) # 123123123123 13123
res = re.split('[ab]' ,'abcd') # 先按'a'分隔得到’‘和'bcd' 在对''和'bcd' 分别按'b'分隔
print(res) # ['','','cd']
res = re.sub('\d', 'H', 'eva3jason4yuan4', 1)
#将数字替换成'H' ,参数1表示只替换1个
print(res) # evaHjason4yuan4
res = re.subn('\d', 'H', 'eva3jason4yuan4')
#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret) # ('evaHjasonHyuanH', 3)
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()) # www.oldboy.com
2.分组别名
res = re.search('www.(?P<content>baidu|oldboy)(?P<hei>.com)', 'www.oldboy.com')
print(res.group()) # www.oldboy.com
print(res.group('content')) # oldboy
print(res.group(0)) # www.oldboy.com
print(res.group(1)) # oldboy
print(res.group(2)) # .com
print(res.group('hei')) # .com
网络爬虫简介
网络爬虫:通过编写代码模拟浏览器发送请求获取数据并按照自己指定的要求筛选出想要的数据
小练习:利用正则表达式筛选出红牛所有的分公司数据并打印或保存
公司名称:
公司地址:
公司邮编:
公司电话:
import re
import requests
# 网络爬虫方式
data = requests.get('http://www.redbull.com.cn/about/branch').text
rr = re.findall("<h2>(.*?)</h2><p class='mapIco'>(.*?)</p><p class='mailIco'>(.*?)</p><p class='telIco'>(.*?)</p>",
data)
for i in rr:
print(f'公司名称:{i[0]} 地址:{i[1]} 邮编:{i[2]} 电话:{i[3]}')
#本地爬虫方式
import re
with open('datas.txt', 'r', encoding='utf-8') as f:
data = f.read()
rr = re.findall('<h2>(.*?)</h2><p class="mapIco">(.*?)</p><p class="mailIco">(.*?)</p><p class="telIco">(.*?)</p>',
data)
r2 = re.findall('data-longitude="(.*?)" data-latitude="(.*?)"', data)
rr = list(zip(rr, r2))
for i in rr:
print(f'公司名称:{i[0][0]} 地址:{i[0][1]} 邮编:{i[0][2]} 电话:{i[0][3]} 经度:{i[1][0]} 纬度{i[1][1]}')