Python正则表达式入门:从匹配HTML标签到网页内容抓取
2026/6/26 11:41:39 网站建设 项目流程

正则表达式不是抓取网页的最佳工具,但它是理解网页结构最快的方式。掌握正则后,你能在不依赖任何第三方库的情况下,快速定位和提取页面中的关键信息。


一、先搞懂5个核心元字符

抓取网页只需要记住这几个:

符号含义网页场景举例
.匹配任意单个字符匹配任意标签内容
*匹配前面的字符0次或多次匹配可有可无的属性
+匹配前面的字符1次或多次匹配必有的内容
?匹配前面的字符0次或1次匹配可选的斜杠
()分组,提取内容提取链接地址

量词补充:{n,m} 表示匹配n到m次。比如 \d{11} 就是匹配11位数字,正好用来匹配手机号。


二、匹配HTML标签:从最简单的开始

HTML标签的基本结构是<标签名 属性="值">内容</标签名>

匹配任意HTML标签

importre html='<div class="content">Hello</div><p>World</p>'# 匹配所有标签pattern=r'<[^>]+>'result=re.findall(pattern,html)print(result)# 输出: ['<div class="content">', '</div>', '<p>', '</p>']

解释:[^>]+的意思是"匹配除了 > 之外的一个或多个字符"。因为HTML标签的结束标志是 >,所以这个写法能准确捕获从 < 开始到 > 结束的完整标签。

匹配指定标签

比如只想拿到所有的链接:

html='<a href="https://example.com">点击</a><a href="/about">关于</a>'pattern=r'<a\s+href="([^"]+)"'links=re.findall(pattern,html)print(links)# 输出: ['https://example.com', '/about']

这里用了()括号做分组,re.findall会自动返回括号内匹配到的内容,也就是链接地址本身,而不是整个a标签。


三、提取网页内容:三个高频场景

场景1:提取所有图片地址

html='<img src="/static/logo.png" alt="logo"><img src="banner.jpg">'pattern=r'<img\s+[^>]*src="([^"]+)"'images=re.findall(pattern,html)print(images)# 输出: ['/static/logo.png', 'banner.jpg']

注意:[^>]*用来跳过src前面可能存在的其他属性(比如alt、class等),这是实战中最容易踩坑的地方。很多教程只写<img src="">,但真实网页的属性顺序是不固定的。

场景2:提取标题和正文

html='<h1>Python正则表达式教程</h1><p>这是第一段内容。</p><p>这是第二段。</p>'title=re.search(r'<h1>(.*?)</h1>',html).group(1)paragraphs=re.findall(r'<p>(.*?)</p>',html)print(title)# Python正则表达式教程print(paragraphs)# ['这是第一段内容。', '这是第二段。']

关键点:用.*?而不是.*?让匹配变成"非贪婪模式",即遇到第一个</h1>就停止,而不是一直匹配到最后一个</h1>

场景3:清洗HTML标签,只留文本

html='<div>保留这个<span>还有这个</span></div><script>删除这个</script>'# 移除所有标签text=re.sub(r'<[^>]+>','',html)print(text)# 输出: 保留这个还有这个删除这个

re.sub是替换函数,把所有匹配到的标签替换为空字符串,剩下的就是纯文本。


四、一个完整的实战:抓取豆瓣电影Top250的电影名和评分

importre# 假设这是从网页获取到的HTML片段page_html=''' <div class="item"> <span class="title">肖申克的救赎</span> <span class="rating_num" property="v:average">9.7</span> </div> <div class="item"> <span class="title">霸王别姬</span> <span class="rating_num" property="v:average">9.6</span> </div> '''# 提取电影名和评分pattern=r'<span class="title">(.*?)</span>.*?<span class="rating_num"[^>]*>(.*?)</span>'results=re.findall(pattern,page_html,re.DOTALL)forname,ratinginresults:print(f'{name}:{rating}分')

输出:

肖申克的救赎: 9.7分 霸王别姬: 9.6分

re.DOTALL.可以匹配换行符,否则中间的换行会导致匹配失败。这是处理多行HTML时必须加的参数。


五、正则的局限性:什么时候该放弃它

正则能处理简单的HTML提取,但遇到以下情况会很痛苦:

  • 标签嵌套超过2层(比如div里面套div再套div)
  • 属性值里包含引号或特殊字符
  • HTML格式不规范(浏览器能渲染但正则匹配不了)

这些情况下,请直接用BeautifulSoup或lxml。正则的定位是"快速处理简单场景",不是"万能解析器"。

推荐切换时机:当你发现正则写到第三层嵌套还匹配不对的时候,就是该换工具的时候。


六、速查表

需求正则表达式
匹配任意标签<[^>]+>
提取a标签链接<a\s+href="([^"]+)"
提取img的src<img\s+[^>]*src="([^"]+)"
提取标签内文本(非贪婪)<tag>(.*?)</tag>
移除所有HTML标签re.sub(r'<[^>]+>', '', html)
匹配11位手机号1[3-9]\d{9}

把这张表存下来,够用80%的网页抓取场景。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询