正则表达式前戏
正则表达式是一门独立的技术 所有编程语言都可以使用
它的作用可以简单的概括为:利用一些特殊符号(也可以直接写需要查找的具体字符)的组合产生一些特殊的含义然后去字符串中筛选出符合条件的数据
筛选数据(匹配数据)
字符组
| 字符组默认匹配方式是挨个挨个匹配 | |
|---|
| [0123456789] | 匹配0到9任意一个数(全写) |
| [0-9] | 匹配0到9任意一个数(缩写) |
| [a-z] | 匹配26个小写英文字母 |
| [A-Z] | 匹配26个大写英文字母 |
| [0-9a-zA-Z] | 匹配数字或者小写字母或者大写字母 |
| 字符组内所有的数据默认都是或的关系 | |
特殊符号
| [^] | 取反操作 匹配除了字符组里面的其他所有字符,注意上尖号在中括号内和中括号意思完全不同 |
|---|
| . | 匹配除换行符以外的任意字符 |
| \w | 匹配数字、字母、下划线 |
| \W | 匹配非数字、非字母、非下划线 |
| \d | 匹配数字 |
| 匹配字符串的开头 |
| $ | 匹配字符串的结尾 |
| a|b | 匹配a或者b(管道符的意思是或) |
| () | 给正则表达式分组 不影响表达式的匹配功能 |
| [^] | 取反操作 匹配除了字符组里面的其他所有字符 |
量词
| * | 匹配零次或多次 默认是多次(无穷次) |
|---|
| + | 匹配一次或多次 默认是多次(无穷次) |
| ? | 匹配零次或一次 作为量词意义不大主要用于非贪婪匹配 |
| {n} | 重复n次 |
| {n,} | 重复n次或更多次 默认是多次(无穷次) |
| {n,m} | 重复n到m次 默认是m次 |
| 正则表达式默认情况下都是贪婪匹配>>>:尽可能多的匹 | 量词必须结合表达式一起使用 不能单独出现 并且只影响左边第一个表达式 jason\d{3} 只影响\d |
贪婪匹配与非贪婪匹配
1.什么是正则表达式的贪婪与非贪婪匹配
如:String str="abcaxc"
Patter p="ab*c"
贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(ab*c)。
非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(ab*c)。
2.编程中如何区分两种模式
下面的都是量词:
{m,n}:m到n个
*:任意多个
+:一个到多个
?:0或一个
贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
非贪婪匹配:在满足匹配时,匹配尽可能短的字符串,使用?来表示非贪婪匹配
几个常用的非贪婪匹配Pattern
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
转义符
| 斜杠与字母的组合有时候有特殊含义 | 如果是在python中使用 还可以在字符串前面加r取消转义 |
|---|
| \n | 匹配的是换行符 |
| \ \n | 匹配的是文本\n |
| \ \ \ \n | 匹配的是文本\n |
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
print(res.group()) a 匹配到一个符合条件的数据就立刻结束
res = re.match('a', 'jason apple eva')
print(res) None 匹配字符串的开头 如果不符合后面不用看了
print(res.group()) 匹配开头符合条件的数据 一个就结束
obj = re.compile('\d{3}') 当某一个正则表达式需要频繁使用的时候 我们可以做成模板
res1 = obj.findall('23423422342342344')
res2 = obj.findall('asjdkasjdk32423')
print(res1, res2)
补充说明
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 requests
from openpyxl import Workbook
res = requests.get('http://redbull.com.cn/about/branch')
print(res.content)
print(res.text)
with open(r'hn.html','wb')as f:
f.write(res.content)
import re
with open(r'hn.html','r',encoding='utf8')as f:
date = f.read()
company_name_list = re.findall('<h2>(.*?)</h2>',date)
company_addr_list = re.findall("<p class='mapIco'>(.*?)</p>",date)
company_email_list = re.findall("<p class='mailIco'>(.*?)</p>",date)
company_phone_list = re.findall("<p class='telIco'>(.*?)</p>",date)
res = zip(company_name_list,company_addr_list,company_phone_list,company_email_list)
wb = Workbook()
wb1 = wb.create_sheet('公司信息表',0)
wb1.sheet_properties.tabColor = "1072BA"
wb1.append(['公司名称','公司地址','公司电话','公司邮箱'])
for i in res:
wb1.append(i)
wb.save(r'全国红牛分公司信息表.xlse')