Python爬虫之正则表达式的使用(三)
正则表达式的使用
re.match(pattern,string,flags=0)
re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
参数介绍:
pattern:正则表达式
string:匹配的目标字符串
flags:匹配模式
正则表达式的匹配模式:
最常规的匹配
1 2 3 4 5 6 7 | import re content = 'hello 123456 World_This is a Regex Demo' print ( len (content)) result = re.match( '^hello\s\d{6}\s\w{10}.*Demo$$' ,content) print (result) print (result.group()) #返回匹配结果 print (result.span()) #返回匹配结果的范围 |
结果运行如下:
1 2 3 4 | 39 <_sre.SRE_Match object ; span = ( 0 , 39 ), match = 'hello 123456 World_This is a Regex Demo' > hello 123456 World_This is a Regex Demo ( 0 , 39 ) |
泛匹配
使用(.*)匹配更多内容
1 2 3 4 | import re content = 'hello 123456 World_This is a Regex Demo' result = re.match( '^hello.*Demo$' ,content) print (result)<br><br> print (result.group()) |
结果运行如下:
1 2 | <_sre.SRE_Match object ; span = ( 0 , 39 ), match = 'hello 123456 World_This is a Regex Demo' > hello 123456 World_This is a Regex Demo |
匹配目标
在正则表达式中使用()将要获取的内容括起来
使用group(1)获取第一处,group(2)获取第二处,如此可以提取我们想要获取的内容
1 2 3 4 5 | import re content = 'hello 123456 World_This is a Regex Demo' result = re.match( '^hello\s(\d{6})\s.*Demo$' ,content) print (result) print (result.group( 1 )) #获取匹配目标 |
结果运行如下:
1 2 | <_sre.SRE_Match object ; span = ( 0 , 39 ), match = 'hello 123456 World_This is a Regex Demo' > 123456 |
贪婪匹配
1 2 3 4 5 | import re content = 'hello 123456 World_This is a Regex Demo' result = re.match( '^he.*(\d+).*Demo$' ,content) print (result) print (result.group( 1 )) |
注意:.*会尽可能的多匹配字符
非贪婪匹配
1 2 3 4 5 | import re content = 'hello 123456 World_This is a Regex Demo' result = re.match( '^he.*?(\d+).*Demo$' ,content) print (result) print (result.group( 1 )) |
注意:.*?会尽可能匹配少的字符
使用匹配模式
在解析HTML代码时会有换行,这时我们就要使用re.S
1 2 3 4 5 6 | import re content = 'hello 123456 World_This ' \ 'is a Regex Demo' result = re.match( '^he.*?(\d+).*?Demo$' ,content,re.S) print (result) print (result.group( 1 )) |
运行结果如下:
1 2 | <_sre.SRE_Match object ; span = ( 0 , 39 ), match = 'hello 123456 World_This is a Regex Demo' > 123456 |
转义
在解析过程中遇到特殊字符,就需要做转义,比如下面的$符号。
import re
content = 'price is $5.00'
result = re.match('^price.*\$5\.00',content)
print(result.group())
总结:尽量使用泛匹配,使用括号得到匹配目标,尽量使用非贪婪模式,有换行就用re.S
re.search(pattern,string,flags=0)
re.search扫描整个字符串并返回第一个成功的匹配。
比如我想要提取字符串中的123456,使用match方法无法提取,只能使用search方法。
1 2 3 4 | import re content = 'hello 123456 World_This is a Regex Demo' result = re.match( '\d{6}' ,content) print (result) |
1 2 3 4 5 | import re content = 'hello 123456 World_This is a Regex Demo' result = re.search( '\d{6}' ,content) print (result) print (result.group()) |
运行结果如下:
1 2 | <_sre.SRE_Match object ; span = ( 6 , 12 ), match = '123456' > 123456 |
匹配演练
可以匹配代码里结构相同的部分,这样可以返回你需要的内容
1 2 3 4 | import re content = '<a title="2009年中信出版社出版图书" href="/doc/2703035-2853985.html" target="_blank" data-log="old:2703035-2853885,new:2703035-2853985" data-cid="sense-list">2009年中信出版社出版图书</a>' result = re.search( '<a.*?new:\d{7}-\d{7}.*?>(.*?)</a>' ,content) print (result.group( 1 )) |
1 | 2009 年中信出版社出版图书 |
re.findall(pattern,string,flags=0)
搜索字符串,以列表形式返回全部能匹配的字串
import re
html ='''
<li>
<a title="网络歌曲" href="/doc/2703035-2853927.html" target="_blank" data-log="old:2703035-2853885,new:2703035-2853927" data-cid="sense-list">网络歌曲</a>
</li>
<li>
<a title="2009年中信出版社出版图书" href="/doc/2703035-2853985.html" target="_blank" data-log="old:2703035-2853885,new:2703035-2853985" data-cid="sense-list">2009年中信出版社出版图书</a>
</li>
'''
result = re.findall('<a.*?new:\d{7}-\d{7}.*?>(.*?)</a>',html,re.S)
count = 0
for list in result:
print(result[count])
count+=1
1 2 | 网络歌曲 2009 年中信出版社出版图书 |
re.sub( pattern,repl,string,count,flags)
re.sub共有五个参数
三个必选参数 pattern,repl,string
两个可选参数count,flags
替换字符串中每一个匹配的字符串后替换后的字符串
1 2 3 4 | import re content = 'hello 123456 World_This is a Regex Demo' content = re.sub( '\d+' ,'',content) print (content) |
运行结果如下:
1 | hello World_This is a Regex Demo |
1 2 3 4 | import re content = 'hello 123456 World_This is a Regex Demo' content = re.sub( '\d+' , 'what' ,content) print (content) |
运行结果如下:
1 | hello what World_This is a Regex Demo |
1 2 3 4 | import re content = 'hello 123456 World_This is a Regex Demo' content = re.sub( '(\d+)' ,r '\1 789' ,content) print (content) |
运行结果如下:
1 | hello 123456 789 World_This is a Regex Demo |
注意:这里\1代表前面匹配的123456
演练
在这里我们替换li标签
1 2 3 4 5 6 7 8 9 10 11 | import re html = ''' <li> <a title="网络歌曲" href="/doc/2703035-2853927.html" target="_blank" data-log="old:2703035-2853885,new:2703035-2853927" data-cid="sense-list">网络歌曲</a> </li> <li> <a title="2009年中信出版社出版图书" href="/doc/2703035-2853985.html" target="_blank" data-log="old:2703035-2853885,new:2703035-2853985" data-cid="sense-list">2009年中信出版社出版图书</a> </li> ''' html = re.sub( '<li>|</li>' ,'',html) print (html) |
运行结果如下,里面就没有li标签
1 2 3 4 | <a title = "网络歌曲" href = "/doc/2703035-2853927.html" target = "_blank" data - log = "old:2703035-2853885,new:2703035-2853927" data - cid = "sense-list" >网络歌曲< / a> <a title = "2009年中信出版社出版图书" href = "/doc/2703035-2853985.html" target = "_blank" data - log = "old:2703035-2853885,new:2703035-2853985" data - cid = "sense-list" > 2009 年中信出版社出版图书< / a> |
compile(pattern [, flags])
该函数根据包含的正则表达式的字符串创建模式对象。可以实现更有效率的匹配
将正则表达式编译成正则表达式对象,以便于复用该匹配模式
1 2 3 4 5 | import re content = 'hello 123456 ' \ 'World_This is a Regex Demo' pattern = re. compile ( 'hello.*?Demo' ,re.S) result = re.match(pattern,content) print (result.group()) |
运行结果如下:
1 | hello 123456 World_This is a Regex Demo |
综合使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | import re html = ''' <div class="slide-page" style="width: 700px;" data-index="1"> <a class="item" target="_blank" href="https://movie.douban.com/subject/26725678/?tag=热门&from=gaia"> <div class="cover-wp" data-isnew="false" data-id="26725678"> <img src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2525020357.jpg" alt="解除好友2:暗网" data-x="694" data-y="1000"> </div> <p> 解除好友2:暗网 <strong>7.9</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/26916229/?tag=热门&from=gaia_video"> <div class="cover-wp" data-isnew="false" data-id="26916229"> <img src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2532008868.jpg" alt="镰仓物语" data-x="2143" data-y="2993"> </div> <p> 镰仓物语 <strong>6.9</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/26683421/?tag=热门&from=gaia"> <div class="cover-wp" data-isnew="false" data-id="26683421"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2528281606.jpg" alt="特工" data-x="690" data-y="986"> </div> <p> 特工 <strong>8.3</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/27072795/?tag=热门&from=gaia"> <div class="cover-wp" data-isnew="false" data-id="27072795"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2521583093.jpg" alt="幸福的拉扎罗" data-x="640" data-y="914"> </div> <p> 幸福的拉扎罗 <strong>8.6</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/27201353/?tag=热门&from=gaia_video"> <div class="cover-wp" data-isnew="false" data-id="27201353"> <img src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2528842218.jpg" alt="大师兄" data-x="679" data-y="950"> </div> <p> 大师兄 <strong>5.2</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/30146756/?tag=热门&from=gaia_video"> <div class="cover-wp" data-isnew="false" data-id="30146756"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2530872223.jpg" alt="风语咒" data-x="1079" data-y="1685"> </div> <p> 风语咒 <strong>6.9</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/26630714/?tag=热门&from=gaia"> <div class="cover-wp" data-isnew="false" data-id="26630714"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2530591543.jpg" alt="精灵旅社3:疯狂假期" data-x="1063" data-y="1488"> </div> <p> 精灵旅社3:疯狂假期 <strong>6.8</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/25882296/?tag=热门&from=gaia_video"> <div class="cover-wp" data-isnew="false" data-id="25882296"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2526405034.jpg" alt="狄仁杰之四大天王" data-x="2500" data-y="3500"> </div> <p> 狄仁杰之四大天王 <strong>6.2</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/26804147/?tag=热门&from=gaia_video"> <div class="cover-wp" data-isnew="false" data-id="26804147"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2527484082.jpg" alt="摩天营救" data-x="1371" data-y="1920"> </div> <p> 摩天营救 <strong>6.4</strong> </p> </a> <a class="item" target="_blank" href="https://movie.douban.com/subject/24773958/?tag=热门&from=gaia_video"> <div class="cover-wp" data-isnew="false" data-id="24773958"> <img src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2517753454.jpg" alt="复仇者联盟3:无限战争" data-x="1968" data-y="2756"> </div> <p> 复仇者联盟3:无限战争 <strong>8.1</strong> </p> </a> </div> ''' count = 0 <br> for list in result:<br> print (result[count])<br> count + = 1 <br><br> |
运行结果如下:
1 2 3 4 5 6 7 8 9 10 | ( '解除好友2:暗网' , '7.9' ) ( '镰仓物语' , '6.9' ) ( '特工' , '8.3' ) ( '幸福的拉扎罗' , '8.6' ) ( '大师兄' , '5.2' ) ( '风语咒' , '6.9' ) ( '精灵旅社3:疯狂假期' , '6.8' ) ( '狄仁杰之四大天王' , '6.2' ) ( '摩天营救' , '6.4' ) ( '复仇者联盟3:无限战争' , '8.1' ) |
正则表达式匹配IP
#IPv4的IP正则匹配表达式 import re #简单的匹配给定的字符串是否是ip地址,下面的例子它不是IPv4的地址,但是它满足正则表达式 if re.match(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$", "272.168,1,1"): print "IP vaild" else: print "IP invaild" #精确的匹配给定的字符串是否是IP地址 if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", "223.168.1.1"): print "IP vaild" else: print "IP invaild" #简单的从长文本中提取中提取ip地址 string_ip = "is this 289.22.22.22 ip ? result = re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", string_ip) if result: print result else: print "re cannot find ip" #精确提取IP result = re.findall(r"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b", string_ip): if result: print result else: print "re cannot find ip #IPv6的正则匹配表达式 string_IPv6="1050:0:0:0:5:600:300c:326b" #匹配是否满足IPv6格式要求,请注意例子里大小写不敏感 if re.match(r"^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}$", string_IPv6, re.I): print "IPv6 vaild" else: print "IPv6 invaild" #提取IPv6,例子里大小写不敏感 result = re.findall(r"(?<![:.\w])(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}(?![:.\w])", string_IPv6, re.I) #打印提取结果 print result
判断字符串中是否含有汉字或非汉字
model中compile值可以根据需要更改,满足不同的检测需求
#判断一段文本中是否包含简体中文 import re zhmodel = re.compile(u'[\u4e00-\u9fa5]') #检查中文 #zhmodel = re.compile(u'[^\u4e00-\u9fa5]') #检查非中文 contents = u'(2014)深南法民二初字第280号' match = zhmodel.search(contents) if match: print(contents) else: print(u'没有包含中文')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?