re库匹配后返回对象及匹配方法简介

官方文档请查看:https://docs.python.org/3/library/re.html

使用软件及版本:Jupyter Notebook (Anaconda3)

使用素材链接:https://pvp.qq.com/web201605/herolist.shtml

几种匹配模式简介

re.Match object 为其基本单元。


方法说明
re.search()检索整个文档,匹配第一个满足表达式的字符串。
re.match()从头开始匹配,匹配第一个满足表达式的字符串。
re.findall()匹配所有满足表达式的字符串,返回一个列表。
re.finditer()匹配所有满足表达式的字符串,返回一个迭代对象。
re.split()按表达式分割字符,参数mxsplit控制最大分割数。
re.sub()替换正则表达式所匹配到的字符,参数count控制最大替换次数。

提前下载网页到本地,后面直接从本地加载。

os.chdir("..\Desktop")

text_path=os.getcwd()+"\download_text.json"

url="https://pvp.qq.com/web201605/herolist.shtml"

r=requests.get(url)

r.encoding=r.apparent_encoding #gbk

if r.status_code == 200:

    with open(text_path,"w+") as f:

        json.dump(r.text,f,ensure_ascii=False)

加载本地文件

text_path=os.getcwd()+"\download_text.json"

with open(text_path,"r") as f:
    
    for line in f:
        
        match_str = json.loads(line)

正则表达式设计

#正则表达式内部以组来区分,每个括号内部便是一个组,想要匹配括号,可以使用 "\(" , "\)" 或者 [(] , [)] 。
#可以用(?P<key>表达式)对组命名;等价于字典,前面是键,后面是值:{key:value};下篇文章会介绍。
hero_extract=r'<li><a href="(herodetail/(\d{3}).shtml)".*?([\u4e00-\u9fa5]{1,5})</a></li>'
#由于字符串中有换行符 "\n" ,故加入flags:re.DOTALL 使得 " . "可以匹配包括换行符在内的所有字符。
hero_extract_pat=re.compile(hero_extract,re.S)

1.   re.search() 方法:

if  match_str:
    
    result=hero_extract_pat.search(match_str)

    if result:

        print(result)

输出结果如下:

<re.Match object; span=(12602, 12849), match='<li><a href="herodetail/506.shtml" target="_blank>

上式即是其匹配到的对象,可以看到 re.search 只匹配且返回一个对象。可以用下面代码来验证。

print(match_str[result.span()[0]-1000:result.span()[0]])
print(match_str[result.span()[1]:result.span()[1]+1000])

结果如下:

字符串确定

可以看到,后面同样的 li 并没有匹配到。

匹配到完整的字符串为:

string=result.group()
print(result.group())
#输出结果如下:
'''
<li><a href="herodetail/506.shtml" target="_blank"><img

                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/506/506.jpg" width="91"

                                        height="91" alt="云中君">云中君</a></li>
'''

看看 match 有哪些属性

print(type(result)) #<class 're.Match'>
print(dir(result))
'''
输出结果如下:
['__class__', '__class_getitem__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string']
'''

前面的为私有属性,我们不作了解,下面这几个属性或方法应该是我们需要掌握的。

['end', 'endpos', 'expand', 'group', \
'groupdict', 'groups', 'lastgroup', \
'lastindex', 'pos', 're', 'regs',\
 'span', 'start', 'string']

1.1 位置属性:

["start","end","span","pos","endpos"]

#输出字符串长度,作为对比。
print(len(match_str)) #output: 46490

#输出匹配到的MATCH对象在原字符串中的位置,等价于 ("result.start()","result.end()").
print(result.span()) #output: (12602, 12849)

#输出匹配目标头部在原字符串中的位置。
print(result.start()) #output: 12602

#输出匹配目标结尾在原字符串中的位置。
print(result.end()) #output: 12849

#输出匹配目标在字符串中开始匹配的位置序列。
print(result.pos) #output: 0

#输出匹配目标在字符串中结束匹配的位置序列。        
print(result.endpos) #output: 46490

'''
关于本例:表达式是 hero_extract_pat ,匹配字符串是 match_str,其长度为 46490 ,\
表达式开始匹配的位置是字符串的第 0 个字符,结束匹配的位置是字符串的最后一位,\
即 46490;匹配到的结果在字符串中的位置是 (12602, 12849),匹配结果的开始位置是字符串的第 12602 个字符,匹配结果的结尾是字符串的第 12849 个。
'''

1.2 条件属性:

["re","string"]

#返回用于匹配的正则表达式,本例为 hero_extract_pat。
print(result.re) #output:re.compile('<li><a href="(herodetail/(\\d{3}).shtml)".*?([\\u4e00-\\u9fa5]{1,5})</a></li>', re.DOTALL)

#输出用于匹配的字符串,本例中为 match_str。
print(result.string) #output: <!DOCTYPE HTML>......</html>

#上式中,result.re 下面也有属于自己的属性,例:result.re.pattern 等,可以自行了解学习。

1.3 组 group 属性:

1. 建立组的概念,在正则表达式中,用“( )”来表示一个组,其序号按从左往右按左括号出现顺序,从1开始计数【0为默认参数,表示匹配到的整个字符串】。

hero_extract 中,共有三个组,分别是:

  1. (herodetail/(\\d{3}).shtml)
  2. (\\d{3})
  3. ([\\u4e00-\\u9fa5]{1,5})

当然,对于组而言,又有属于它的性质,如:命名引用 等,这里不作介绍。

["groups","group","lastgroup","groupdict","lastindex"]

#输出一个元组,元组元素为匹配到的值,本例中只有三个组,故元组有三个元素。
print(result.groups()) #output:('herodetail/506.shtml', '506', '云中君')

#这个方法有两种用法,分别是:
#1. group()不加参数【默认参数为0】,返回字符串,值为匹配到的整个字符
print(result.group()) #or print(result.group(0))
""" 
output: 
<li><a href="herodetail/506.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/506/506.jpg" width="91"
                                        height="91" alt="云中君">云中君</a></li>
"""
#2. group()加不为0的参数,输入组的索引,则返回对应的匹配到的组。
print(result.group(1)) #output: herodetail/506.shtml
print(result.group(2)) #output: 506

#以字典形式返回匹配到的结果,前提是在正则表达式中定义了名称,本例中,输出为 {} 。
print(result.groupdict()) #output: {}
#改写一下正则表达式,则输出结果就会改变。
#改变后 :hero_extract=r'<li><a href="(?P<hero_url>herodetail/(\d{3}).shtml)".*?([\u4e00-\u9fa5]{1,5})</a></li>'
print(result.groupdict()) #output: {'hero_url': 'herodetail/506.shtml'}
#改变后 :hero_extract=r'<li><a href="(?P<hero_url>herodetail/(?P<hero_info_num>\d{3}).shtml)".*?([\u4e00-\u9fa5]{1,5})</a></li>'
print(result.groupdict()) #output: {'hero_url': 'herodetail/506.shtml', 'hero_info_nim': '506'}

#属性,不加括号调动,返回字符:若最后一个组有名字,则返回 “key” ,否则返回 None.只于最后一组是否有名称有关。
print(result.lastgroup) #output: None
#改变后:hero_extract=r'<li><a href="(herodetail/(\d{3}).shtml)".*?(?P<hero_name>[\u4e00-\u9fa5]{1,5})</a></li>'
print(result.lastgroup) #output: hero_name

#同上,为属性,不加括号调动,返回值为匹配结果group的数目。
print(result.lastindex) #output:3

1.4 不常用属性

["expand","regs"]
#目前我也不太搞懂,后面搞懂补上。
print(result.expand()) #output:

#返回一个元组,其元素为各个组字符串在源字符串中的位置索引。相当于:
"""
temp_list=[result.span(),]

for item in result.groups():
    
    temp_list.append((match_str.find(item),match_str.find(item)+len(item)))
    
regs=tuple(temp_list)

print(regs)
结果略有不同,这是网页页面结构所导致的,主要的是理解其含义。
"""
print(result.regs) #output:((12602, 12849), (12615, 12635), (12626, 12629), (12837, 12840))

2.  特殊 re.match() 方法:

1.此方法是  从头(head) 第一个字符开始匹配,

#此方法来匹配match_str结果为空,因为第一行不是<li...开始。
result=hero_extract_pat.match(match_str)
#等价于
if result: #return :False/because result=None

	print(result)
	
#我们来匹配前面得到的字符串string吧。
result_t=hero_extract_pat.match(string)
#因为match是从头开始匹配
if result:

	print(result)
	#output: <re.Match object; span=(0, 247), match='<li><a href="herodetail/506.shtml" target="_blank>

3.   re.findall() 方法:

匹配整个字符串,提取符合表达式的片段,返回一个列表,列表单个元素为一个 groups 格式的元组,


result=hero_extract_pat.findall(match_str)

if result:

	print(result)
	#output: [('herodetail/506.shtml', '506', '云中君'),...]

#想要查看元素,按列表处理即可。
for item in result:

	print(item)
	#output: ('herodetail/506.shtml', '506', '云中君')

4.   re.finditer() 方法:

匹配整个字符串,提取符合表达式的片段,返回一个 match 迭代对象,列表单个元素为 re.Match 对象,具有 span() 等属性和方法


result=hero_extract_pat.finditer(match_str)

if result:

	print(result)
	#output: 返回元素属性及储存地址- <callable_iterator object at 0x0000023E0863A460>
	
	#进行遍历,查看元素
	for item in result:
	
		print(item)
		#output:<re.Match object; span=(12602, 12849), match='<li><a href="herodetail/506.shtml" target="_blank>
		
	   #查看其groups 和 span()
		print(item..groups(),item.span(),item.regs)
	   #output: ('erodetail/506.shtml', '506', '云中君') (12602, 12849) ((12602, 12849), (12615, 12635), (12626, 12629), (12837, 12840))

5.    re.split() 方法:

分割字符串,返回列表,可以通过 maxsplit 参数来控制最大分割次数,

#因为源文件太长,这里我们取中间一部分,看看split方法。
#先看看源字符串相同位置:
print(match_str[12000,14000]
"""
output:
li>
                        </ul>
                        <div class="herosearch">
                            <input type="text" id="search" name="search" class="herosearch-input" value="请输入你想要搜索的英雄名">
                            <a href="javascript:void(0);" class="herosearch-icon" title="点击搜索" id="searchBtn"></a>
                        </div>
                    </div>
                    <div class="herolist-content">
                        <p id="JErroTips" style="display:none;">输入英雄不存在,请重新输入</p>
                        <ul class="herolist clearfix">
                            <li><a href="herodetail/506.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/506/506.jpg" width="91"
                                        height="91" alt="云中君">云中君</a></li>
                            <li><a href="herodetail/505.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/505/505.jpg" width="91"
                                        height="91" alt="瑶">瑶</a></li>
                            <li><a href="herodetail/529.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/529/529.jpg" width="91"
                                        height="91" alt="盘古">盘古</a></li>
                            <li><a href="herodetail/511.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/511/511.jpg" width="91"
                                        height="91" alt="猪八戒">猪八戒</a></li>
                            <li><a href="herodetail/515.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/515/515.jpg" width="91"
                                        height="91" alt="嫦娥">嫦娥</a></li>
                            <li><a href="herodeta
"""
result=hero_extract_pat.split(match_str[12000:14000])

if result:

	print(result)
	"""
	output:
	['li>\r\n                        </ul>\r\n                        <div class="herosearch">\r\n                            <input type="text" id="search" name="search" class="herosearch-input" value="请输入你想要搜索的英雄名">\r\n                            <a href="javascript:void(0);" class="herosearch-icon" title="点击搜索" id="searchBtn"></a>\r\n                        </div>\r\n                    </div>\r\n                    <div class="herolist-content">\r\n                        <p id="JErroTips" style="display:none;">输入英雄不存在,请重新输入</p>\r\n                        <ul class="herolist clearfix">\r\n                            ', 'herodetail/506.shtml', '506', '云中君', '\r\n                            ', 'herodetail/505.shtml', '505', '瑶', '\r\n                            ', 'herodetail/529.shtml', '529', '盘古', '\r\n                            ', 'herodetail/511.shtml', '511', '猪八戒', '\r\n                            ', 'herodetail/515.shtml', '515', '嫦娥', '\r\n                            <li><a href="herodeta']
""" 

加入分割次数限制:

if  match_str:
    
    result=hero_extract_pat.split(match_str[12000:14000],maxsplit=1)

    if result:
        
        print(result)
        """
		output:
		['li>\r\n                        </ul>\r\n                        <div class="herosearch">\r\n                            <input type="text" id="search" name="search" class="herosearch-input" value="请输入你想要搜索的英雄名">\r\n                            <a href="javascript:void(0);" class="herosearch-icon" title="点击搜索" id="searchBtn"></a>\r\n                        </div>\r\n                    </div>\r\n                    <div class="herolist-content">\r\n                        <p id="JErroTips" style="display:none;">输入英雄不存在,请重新输入</p>\r\n                        <ul class="herolist clearfix">\r\n                            ', 'herodetail/506.shtml', '506', '云中君', '\r\n                            <li><a href="herodetail/505.shtml" target="_blank"><img\r\n                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/505/505.jpg" width="91"\r\n                                        height="91" alt="瑶">瑶</a></li>\r\n                            <li><a href="herodetail/529.shtml" target="_blank"><img\r\n                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/529/529.jpg" width="91"\r\n                                        height="91" alt="盘古">盘古</a></li>\r\n                            <li><a href="herodetail/511.shtml" target="_blank"><img\r\n                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/511/511.jpg" width="91"\r\n                                        height="91" alt="猪八戒">猪八戒</a></li>\r\n                            <li><a href="herodetail/515.shtml" target="_blank"><img\r\n                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/515/515.jpg" width="91"\r\n                                        height="91" alt="嫦娥">嫦娥</a></li>\r\n                            <li><a href="herodeta']

"""
              

可以看到,在加了 maxsplit 之后,与上面没有限制最大分割次数的做对比,发现其在第一个英雄名称为“云中君”之后,便没有继续分割字符串,而上面一个则分割可以匹配到的所有片段。用 len 方法查看其列表长度:结果如下:

#未限制maxsplit:
print(len(result)) #output: 21
#限制了maxsplit:
print(len(result)) #output: 5

6.    re.sub() 方法:

替换表达式所匹配到的参数,并返回替换后的字符串。

#源文件还是太长,不方便在本例中查看,我们截取片段。
result=hero_extract_pat.sub("正则表达式学习",match_str[12000:14000])
    
if result:

	print(result)
	"""
	output:
	li>
                        </ul>
                        <div class="herosearch">
                            <input type="text" id="search" name="search" class="herosearch-input" value="请输入你想要搜索的英雄名">
                            <a href="javascript:void(0);" class="herosearch-icon" title="点击搜索" id="searchBtn"></a>
                        </div>
                    </div>
                    <div class="herolist-content">
                        <p id="JErroTips" style="display:none;">输入英雄不存在,请重新输入</p>
                        <ul class="herolist clearfix">
                            正则表达式学习
                            正则表达式学习
                            正则表达式学习
                            正则表达式学习
                            正则表达式学习
                            <li><a href="herodeta

	""" 
#加入count参数,控制最大替换次数,则结果如下:
if  match_str:
    #控制最多替换三个满足表达式的片段,超过则不替换
    result=hero_extract_pat.sub("正则表达式学习",match_str[12000:14000],count=3

    if result:
        
        print(result)
       """
		output:
		li>
                        </ul>
                        <div class="herosearch">
                            <input type="text" id="search" name="search" class="herosearch-input" value="请输入你想要搜索的英雄名">
                            <a href="javascript:void(0);" class="herosearch-icon" title="点击搜索" id="searchBtn"></a>
                        </div>
                    </div>
                    <div class="herolist-content">
                        <p id="JErroTips" style="display:none;">输入英雄不存在,请重新输入</p>
                        <ul class="herolist clearfix">
                            正则表达式学习
                            正则表达式学习
                            正则表达式学习
                            <li><a href="herodetail/511.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/511/511.jpg" width="91"
                                        height="91" alt="猪八戒">猪八戒</a></li>
                            <li><a href="herodetail/515.shtml" target="_blank"><img
                                        src="//game.gtimg.cn/images/yxzj/img201606/heroimg/515/515.jpg" width="91"
                                        height="91" alt="嫦娥">嫦娥</a></li>
                            <li><a href="herodeta
       """       

以上便是本次的所有内容,关于正则表达式中的 flags ,下期再见。

如有错误,请及时指正,提前感谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落寞红颜玉玫瑰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值