
本文介绍如何通过正则表达式匹配而非分割,准确提取包含起始与结束标签的完整 html 片段(如 `
- ...
在处理 HTML 片段时,若目标是按特定成对标记(如 <li>...</li>、<ul>...</ul>、<h2>...</h2> 等)切分字符串并保留完整标签结构,直接使用 re.split() 会破坏标签配对关系——它仅在标签处断开,导致起始/结束标签被分离,内容错位。正确做法是改用 re.finditer() 进行匹配(match),主动捕获“开–闭”成对出现的完整标签块。
核心正则表达式如下:
import re pattern = r"<(p|li|ul|ol|dl|h1|h2|h3|h4|h5|h6)>[^<]*</\1>" subject = '<p> Some text some text. </p> <p> Another text </p>. <li> some list </li>. <ul> another list </ul>' matches = [match.group(0) for match in re.finditer(pattern, subject, re.DOTALL)] print(matches) # 输出: # ['<p> Some text some text. </p>', '<p> Another text </p>', '<li> some list </li>', '<ul> another list </ul>']
✅ 关键设计解析:
- (p|li|ul|ol|dl|h1|...|h6):捕获组,限定支持的成对标签名;
- [^<]*:非贪婪匹配标签内文本(不含 <,避免跨标签误匹配);
- </\1>:反向引用,确保闭合标签与开头标签名称严格一致(如 <li> 必须对应 </li>);
- re.DOTALL:使 . 可匹配换行符,支持多行内容;
⚠️ 重要限制与注意事项:
立即学习“前端免费学习笔记(深入)”;
- 此正则仅适用于简单、规范、无嵌套的单层标签(例如 <p>text</p> ✅,但 <ul><li>item</li></ul> ❌ —— 因 [^<]* 会提前终止于内部 <li>);
- 不支持自闭合标签(如 <img />)、属性(如 <div class="x">)、注释或 CDATA;
- 真实 HTML 文档中强烈建议使用 DOM 解析器(如 BeautifulSoup 或 lxml),它们能稳健处理嵌套、属性、命名空间、非法结构及编码问题。例如:
from bs4 import BeautifulSoup
soup = BeautifulSoup(subject, 'html.parser')
for tag in soup.find_all(['p', 'li', 'ul', 'ol', 'dl', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']):
print(str(tag))? 总结:
正则匹配成对标签是一种轻量级、可控的文本预处理手段,适用于已知结构简单的 HTML 片段(如 CMS 导出内容、模板片段)。但一旦涉及嵌套、动态属性或容错需求,务必转向专业 HTML 解析库——正则不是 HTML 的朋友,DOM 才是。











