首页 > 其他分享 >day 09 9.1 数据解析之正则

day 09 9.1 数据解析之正则

时间:2023-04-20 17:23:52浏览次数:52  
标签:匹配 09 ret 9.1 re 正则 com findall day

第三章. 数据解析之正则

Regular Expression,译作正则表达式或正规表示法,表示有规则的表达式,意思是说,描述一段文本排列规则的表达式。

正则表达式并不是Python的一部分。而是一套独立于编程语言,用于处理复杂文本信息的强大的高级文本操作工具。正则表达式拥有自己独特的规则语法以及一个独立的正则处理引擎,我们根据正则语法编写好规则(模式)以后,引擎不仅能够根据规则进行模糊文本查找,还可以进行模糊分割,替换等复杂的文本操作,能让开发者随心所欲地处理文本信息。正则引擎一般由编程语言提供操作,像python就提供了re模块或regex模块来调用正则处理引擎。

正则表达式在处理文本的效率上不如系统自带的字符串操作,但功能却比系统自带的要强大许多。

最早的正则表达式来源于Perl语言,后面其他的编程语言在提供正则表达式操作时基本沿用了Perl语言的正则语法,所以我们学习python的正则以后,也可以在java,php,go,javascript,sql等编程语言中使用。

正则对字符串或文本的操作,无非是分割、匹配、查找和替换。

在线测试工具 http://tool.chinaz.com/regex/

【1】元字符(Metacharacters)

元字符是具有特殊含义的字符。

元字符 描述
. 叫通配符、万能通配符或通配元字符,匹配1个除了换行符\n以外任何原子
[] 匹配一个中括号中出现的任意原子
[^原子] 匹配一个没有在中括号出现的任意原子
+ 叫加号贪婪符,指定左边原子出现1次或多次
***** 叫星号贪婪符,指定左边原子出现0次或多次
? 叫非贪婪符,指定左边原子出现0次或1次
{n,m} 叫数量范围贪婪符,指定左边原子的数量范围,有{n},{n, }, {,m}, {n,m}四种写法,其中n与m必须是非负整数。
^ 叫开始边界符或开始锚点符,匹配一行的开头位置
$ 叫结束边界符或结束锚点符,匹配一行的结束位置
| 指定原子或正则模式进行二选一或多选一
() 对原子或正则模式进行捕获提取和分组划分整体操作,
\ 转义字符,可以把原子转换特殊元字符,也可以把特殊元字符转成原子。
import re
"""re.findall(正则模式, 文本)  基于正则模式查找所有匹配的文本内容"""
# part1: 通配符->.  字符集-> []
ret1 = re.findall("a", "a,b,c,d,e")
ret1 = re.findall(".", "a,b,c,d,e")
ret1 = re.findall("[ace]", "a,b,c,d,e")
ret1 = re.findall("[a-z]", "a,b,c,d,e")
ret1 = re.findall("[0-9]", "1,2,3,4,5")
ret1 = re.findall("\d", "1,2,3,4,5")
ret1 = re.findall("[0-9a-z]", "1,a,2,b,3")
ret1 = re.findall("[^a-z]", "1,a,2,b,3")
ret1 = re.findall("[^0-9,]", "1,a,2,b,3")
print(ret1)

# part2:重复元字符-> + * {} ?
ret2 = re.findall("[0-9a-zA-Z]", "apple,banana,orange,melon")
ret2 = re.findall("\w", "apple,banana,orange,melon")
ret2 = re.findall("\w+", "apple,banana,orange,melon")
ret2 = re.findall("\w+?", "apple,banana,orange,melon")  # 取消贪婪匹配
ret2 = re.findall("\w*", "apple,banana,orange,melon")
ret2 = re.findall("\w{6}", "apple,banana,orange,melon")

# part3: 位置元字符-> ^ $
ret3 = re.findall("^\w{5}", "apple,banana,peach,orange,melon")
ret3 = re.findall("\w{5}$", "apple,banana,peach,orange,melon")
ret3 = re.findall("^\w{5}$", "apple,banana,peach,orange,melon")
print(ret3)

# part4:
# | 指定原子或正则模式进行二选一或多选一
# () 具备模式捕获的能力,也就是优先提取数据的能力,通过(?:) 可以取消模式捕获
ret4 = re.findall(",\w{5},", ",apple,banana,peach,orange,melon,")  # 筛选出5个字符的单词
ret4 = re.findall(",(\w{5}),", ",apple,banana,peach,orange,melon,")  # 筛选出5个字符的单词
ret4 = re.findall("\w+@\w+\.com", "[email protected],[email protected],....")  # 筛选出5个字符的单词
ret4 = re.findall("(\w+)@qq\.com", "[email protected],[email protected],....")  # 筛选出5个字符的单词
ret4 = re.findall("(?:\w+)@(?:qq|163)\.com", "[email protected],[email protected],....")  # 筛选出5个字符的单词
print(ret4)

# part5:  转义符-> \d \D  \w \W      \n    \s \S  \b \B
""" \b 1个单词边界原子 """
txt = "my name is nana. nihao,nana"
ret = re.findall(r"na", txt)
ret = re.findall(r"\bna", txt)
ret = re.findall(r"\bna\w{2}", txt)
print(ret)  # ['na', 'na', 'na']

转义元字符是\开头的元字符,由于某些正则模式会在开发中反复被用到,所以正则语法预定义了一些特殊正则模式以方便我们简写。

元字符 描述 示例
\d 匹配一个数字原子,等价于[0-9] \d
\D 匹配一个非数字原子。等价于[^0-9][^\d] "\D"
\b 匹配一个单词边界原子,也就是指单词和空格间的位置。 er\b
\B 匹配一个非单词边界原子,等价于 [^\b] r"\Bain"r"ain\B"
\n 匹配一个换行符
\t 匹配一个制表符,tab键
\s 匹配一个任何空白字符原子,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v] "\s"
\S 匹配一个任何非空白字符原子。等价于[^ \f\n\r\t\v][^\s] "\S"
\w 匹配一个包括下划线的单词原子。等价于[A-Za-z0-9_] "\w"
\W 匹配任何非单词字符。等价于[^A-Za-z0-9_][^\w] "\W"

注意:python本身没有内置正则处理的,python中的正则就是一段字符串,我们需要使用python模块中提供的函数把字符串发送给正则引擎,正则引擎会把字符串转换成真正的正则表达式来处理文本内容。

【2】re模块中的常用函数

re模块提供了一组正则处理函数,使我们可以在字符串中搜索匹配项:

函数 描述
findall 按指定的正则模式查找文本中所有符合正则模式的匹配项,以列表格式返回结果。
search 在字符串中任何位置查找首个符合正则模式的匹配项,存在则返回re.Match对象,不存在返回None
match 判定字符串开始位置是否匹配正则模式的规则,匹配则返回re.Match对象,不匹配返回None
split 按指定的正则模式来分割字符串,返回一个分割后的列表
sub 把字符串按指定的正则模式来查找符合正则模式的匹配项,并可以替换一个或多个匹配项成其他内容。

【2.1】findall

def findall(pattern, string, flags=0)

findall()函数返回包含所有匹配项的列表,如果找不到匹配项,则返回一个空列表。

【2.2】search

def search(pattern, string, flags=0)

search()函数搜索匹配的字符串,如果匹配上则返回匹配对象re.Match。如果有多个匹配项,则仅返回匹配项的第一个匹配项,如果找不到匹配项,则返回值为None

import re

ret = re.search("1[3-9]\d{9}", "我的手机号码是13928835900,我女朋友的手机号是15100363326")
print(ret)
print(ret.start(), ret.end(), ret.span())
print(ret.group())

ret = re.search("(?P<tel>1[3-9]\d{9}).*?(?P<email>\[email protected])", "我的手机号码是13928835900,我的邮箱是[email protected]")
print(ret)
print(ret.group("tel"))
print(ret.group("email"))

【2.3】match

def match(pattern, string, flags=0)

match()函数搜索匹配的字符串开始位置,如果匹配上则返回匹配对象,如果找不到匹配项,则返回值为None

【2.4】split

def split(patter, string, maxsplit=0, flags=0)

split()函数返回一个列表,对字符串进行正则分割。

import re

txt = "my name is moluo"
ret = re.split("\s", txt)
print(ret)  # ['my', 'name', 'is', 'moluo']

可以通过指定maxsplit参数来控制分割的次数,例如,仅在第1次出现时才拆分字符串:

import re

txt = "my  name        is    yuan"
ret = re.split("\s+", txt)
print(ret)

【2.5】sub和subn

def sub(pattern, repl, string, count=0, flags=0)  返回匹配后的结果
def subn(pattern, repl, string, count=0, flags=0)  返回匹配后的结果和次数

sub()函数用选择的文本替换匹配:

import re

txt = "my  name        is    yuan"
# ret = re.sub("\s+"," " ,txt)
ret = re.sub("\s+", " ", txt, 2)
print(ret)

【2.6】compile()

def compile(pattern, flags=0)
import re

re_email = re.compile(r"(?:\+86)?1[3-9]\d{9}")
ret = re_email.findall("15100649928,[email protected],13653287791,[email protected]")
print(ret)

如果一个正则表达式要使用几千遍,每一次都会编译,出于效率的考虑进行正则表达式的编译,就不需要每次都编译了,节省了编译的时间,从而提升效率

【3】正则进阶

【3.1】.*?

import re

text = '<12> <xyz> <!@#$%> <1a!#e2> <>'

ret = re.findall("<\d+>", text)
ret = re.findall("<\w+>", text)
ret = re.findall("<.+>", text)
ret = re.findall("<.+?>", text)
ret = re.findall("<.*?>", text)

print(ret)

【3.2】模式修正符

模式修正符,也叫正则修饰符,模式修正符就是给正则模式增强或增加功能的。

通用flags(修正符)

说明
re.I 是匹配对大小写不敏感
re.L 做本地化识别匹配
re.M 多行匹配,影响到^和$
re.S 使.匹配包括换行符在内的所有字符
re.U 根据Unicode字符集解析字符,影响\w、\W、\b、\B
re.X 通过给予我们功能灵活的格式以便更好的理解正则表达式
import re

text = """
<12
>
 
 <x
 yz> 
 
 <!@#$%> 
 
 <1a!#
 e2> 
 
 <>
"""

ret = re.findall("<.*?>", text)
ret = re.findall("<.*?>", text, re.S)

print(ret)

练习:豆瓣Top250页面解析


【4】练习

工作中,正则一般用于验证数据、校验用户输入的信息、爬虫、运维日志分析等。其中如果是验证用户输入的数据:

场景 正则表达式
用户名 ^[a-z0-9_-]{3,16}$
密码 ^[a-z0-9_-]{6,18}$
手机号码 ^(?:\+86)?1[3-9]\d{9}$
颜色的十六进制值 `^#?([a-f0-9]
电子邮箱 ^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+\.[a-z]+$
URL `^(?:https://
IP 地址 `((2[0-4]\d
HTML 标签 ^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>
utf-8编码下的汉字范围 ^[\u2E80-\u9FFF]+$
1、编写正则,匹配整数或者小数(包括正数和负数)

2、编写正则,匹配年月日日期 格式2018-12-31

3、编写正则,匹配qq号 5-12

4、编写正则,11位的电话号码

5、编写正则,长度为8-10位的用户密码 : 包含数字字母下划线

6、编写正则,从18位省份证中提取用户生日日期

7、编写正则,从文本"a@com  [email protected] [email protected]  [email protected]   [email protected]"中匹配qq邮箱地址

8、从以下多行文本中提取href=""中的双引号的值,并提取标签内容 <a>内容<a>
"""
<a href="http://www.badu.com/s?wd=hahaha">hahaha</a>
<a href="http://www.tmall.com/">tmall</a>
<a href="http://www.tmall.com/">tmall</a>
"""

课堂代码

import re

"""
1、编写正则,匹配文本中的整数或者小数(包括正数和负数)
"""
# txt = "10.3 10 20 -20 +20 --20 ++20 -30.5444"
# # ret = re.findall(r"-?\+?\d+", txt)
# ret = re.findall(r"[\+\-]?(?:(?:\d+\.\d+)|(?:\d+))", txt)
# print(ret)
# # ['10', '3', '10', '20', '-20', '+20', '-20', '+20']



"""
2、编写正则,匹配年月日日期 格式: 2018-12-31
"""

# txt = "2018-12-31  2018-12-01 2018-12  2018-31 0000-12-31 2018-1-31 2018-01-31  20-01-31  20-01-1  2020-1-1  2020-01-01"
# ret = re.findall(r"[12]\d{3}-\d+-\d+", txt)
# print(ret)  # ['2018-12-31', '2018-12-01', '2018-1-31', '2018-01-31', '2020-1-1', '2020-01-01']
#

"""
3、编写正则,匹配qq号 5-12数字
"""
# txt = "20181231  40001 2202020133  13311233220222 20202012024222 222050sss2222  33020202222  2001  202011  2020.0101222"
# ret = re.findall(r"[1-9]\d{4,11}", txt)
# print(ret)  # ['20181231', '40001', '2202020133', '133112332202', '202020120242', '222050', '33020202222', '202011', '101222']



"""
4、编写正则,11位的手机号码
"""
# txt = "1331234546 1501233453 15812345678  158-1234-5678  158 1234 5678   20022221111  10012345678  19012345678"
# ret = re.findall(r"1[3-9]\d{9}", txt)
# print(ret)  #
#
# # 如果 158-1234-5678 和 158 1234 5678也算呢?
# txt = "1331234546 1501233453 15812345678  158-1234-5678  158 1234 5678   20022221111  10012345678  19012345678"
# ret = re.findall(r"1[3-9]\d[\- ]?\d{4}[\- ]?\d{4}", txt)
# print(ret)  #


"""
5、编写正则,长度为8-10位的用户密码 : 包含数字字母下划线
"""
# password = input("请输入长度为8-10位的用户密码(包含数字字母下划线):")
# ret = re.match(r"^\w{8,10}$", password)
# print(ret)

"""
6、编写正则,从18位省份证中提取用户生日日期
"""
# idCard = "51142119991021155x"
# ret = re.findall(r"^[1-6]\d{5}(\d{8})\d{3}[\dxX]$", idCard)
# # ret = re.findall(r"^(?:1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5])\d{4}(\d{8})\d{3}[\dxX]$", idCard)
# print(ret)

"""
7、编写正则,从文本"a@com  [email protected] [email protected]  [email protected]   [email protected]"中匹配qq邮箱地址
"""
# txt = "a@com  [email protected] [email protected]  [email protected]   [email protected]"
# ret = re.findall(r"\w+@\w+\.\w+(?:.cn)?", txt)
# print(ret)  # ['[email protected]', '[email protected]', '[email protected]', '[email protected]']

"""
8、从以下多行文本中提取href=""中的双引号的值,并提取标签内容 <a>内容<a>
"""

# txt = """
# <a href="http://www.badu.com/s?wd=hahaha">hahaha</a>
# <a href="http://www.tmall.com/">tmall</a>
# <a href="http://www.tmall.com/">tmall</a>
# """
# ret = re.findall(r'<a href="(?P<href>.*?)">(?P<content>.*?)</a>', txt, re.M+re.S)
# print(ret)

标签:匹配,09,ret,9.1,re,正则,com,findall,day
From: https://www.cnblogs.com/dream-ze/p/17337546.html

相关文章

  • Day 26 26.1 JS进阶之JS对象
    JS进阶之JS对象【一】、字符串对象字符串创建(两种方式)变量=“字符串”字串对象名称=newString(字符串)varstr1="helloworld";//推荐varstr1=newString("helloword");//字符串对象的操作varstr="hello";//这就是字符串对象console.log(str);//......
  • day 04 4.2 web开发核心之【二】
    web开发核心之flask【一】基于flask搭建web网站fromflaskimportFlask,render_templateapp=Flask(__name__,template_folder="templates")@app.get("/index")defindex():returnrender_template("index.html")@app.get("/timer&q......
  • day 05 5.1 前端基础之HTML
    前端基础之HTML了解了web相关基本概念以后,我们开始正式接触网页开发,网页开发的基础是HTML,所以,本章内容主要分两部分,一是介绍HTML的相关概念、发展历史,二是创建HTML网页文档和认识HTML的基本结构。我们学会如何新建一个HTML页面和熟记HTML文档的基本结构和主要标签。......
  • day 03 3.1 Python重要数据类型
    重要数据类型5.1、列表5.1.1、列表声明在实际开发中,经常需要将一组(不只一个)数据存储起来,以便后边的代码使用。列表就是这样的一个数据结构。列表会将所有元素都放在一对中括号[]里面,相邻元素之间用逗号,分隔,如下所示:[element1,element2,element3,...,elementn......
  • day 04 4.1web开发核心之http协议
    web开发核心之http协议http协议1.什么是请求头请求体,响应头响应体2.URL地址包括什么3.get请求和post请求到底是什么4.Content-Type是什么【一】简介HTTP协议是HyperTextTransferProtocol(超文本传输协议)的缩写,是用于万维网(WWW:WorldWideWeb)服务器与本地浏览......
  • day 01 1.1 Python基础之编程语言介绍
    Python基础之编程语言介绍1.1、什么是编程语言编程语言是用来控制计算机的一系列指令(Instruction),它有固定的格式和词汇(不同编程语言的格式和词汇不一样)。就像我们中国人之间沟通需要汉语,英国人沟通需要英语一样,人与计算机之间进行沟通需要一门语言作为介质,即编程语言。编程语言......
  • day 01 1.2 Python基础之Python语言介绍
    Python语言介绍2.1、了解Python语言Python是1989年荷兰人GuidovanRossum(简称Guido)在圣诞节期间为了打发时间,发明的一门面向对象的解释性编程语言。Python来自Guido所挚爱的电视剧MontyPython'sFlyingCircus。Guido对于Python的设计理念就是一门介于shell和C......
  • ZROI 十连测 Day4
    上一次写题解也是若干年前的事了。不过今天的题确实比较好改。命题签到题。状压一下看是任意还是存在,从前边两个状态与或者或出来。#include<cstdio>#include<iostream>#include<algorithm>#include<cmath>usingnamespacestd;intn,q,dp[21][1<<20];chars[1<<20]......
  • 09-内置对象扩展:Set数据结构
    title:09-内置对象扩展:Set数据结构publish:trueSet数据结构Set数据结构的介绍ES6提供了新的数据结构Set。Set类似于数组,但成员的值都是唯一的,没有重复的值。Set的应用有很多。比如,在H5页面的搜索功能里,用户可能会多次搜索重复的关键字;但是在数据存储上,不需要存......
  • AtCoder Regular Contest 109 F 1D Kingdom Builder
    洛谷传送门AtCoder传送门考虑判断一个终止态是否可达。如果只有一个棋子连续段那一定可达;否则就存在\(\ge2\)个连续段。此时把放棋子看成删除,那么限制就是如果删除一个孤立的棋子(两边没有棋子)且还有别的格子有棋子,这个棋子的颜色异于其他连续段的两边棋子的颜色。设第一......