如何在BeautifulSoup对象中移除无信息冗余HTML <div>标签?
清理BeautifulSoup中的冗余
<div>标签 刚好做过类似的HTML清理需求,这种纯粹用来嵌套、既不带任何属性也不含实际内容的<div>确实烦人,尤其是某些自动生成的HTML会搞出一堆没用的层级。从树结构的角度来说,我们要做的就是合并那些仅作为“空容器”的嵌套div节点——把它们的子节点直接提升到父节点的位置,同时移除完全空的div。
实现思路
核心逻辑是遍历DOM树,从最底层的节点开始向上处理:
- 找到满足以下条件的
<div>:无任何属性(class/style/id等)、唯一子节点也是<div>、自身无有效文本内容 - 将这类节点替换成它的子节点,实现层级扁平化
- 最后移除那些完全空的、没有任何内容或子节点的
<div>
代码实现
from bs4 import BeautifulSoup # 原始HTML html = """ <html> <body> <div> <div> <div> <div> <div> <div> Close </div> </div> </div> </div> </div> <div> <div> <div style="width:80px"> <div> </div> <div> <button> Close </button> </div> </div> </div> </div> </div> <div> </div> </body> </html> """ # 解析HTML soup = BeautifulSoup(html, 'html.parser') def remove_redundant_divs(node): # 先递归处理所有子节点,从下往上清理,避免遗漏深层嵌套 for child in list(node.children): if child.name == 'div': remove_redundant_divs(child) # 判断当前节点是否为冗余div if (node.name == 'div' and not node.attrs # 无任何属性 and len(list(node.children)) == 1 # 仅有一个子节点 and list(node.children)[0].name == 'div'): # 子节点也是div # 用子节点替换当前节点,实现层级提升 node.replace_with(list(node.children)[0]) # 开始清理冗余div remove_redundant_divs(soup.body) # 移除完全空的div(没有文本、没有子节点) for empty_div in soup.find_all('div', string=lambda s: s is None or s.strip() == '', recursive=True): if not list(empty_div.children): empty_div.decompose() # 输出清理后的HTML print(soup.prettify())
效果验证
运行后会得到你想要的结构:
<html> <body> <div> Close </div> <div style="width:80px"> <button> Close </button> </div> </body> </html>
注意事项
- 递归处理顺序是从下往上,这样深层嵌套的冗余div会先被清理,上层的div可能会因为子节点被替换后变成冗余节点,进而被处理
- 只有完全符合“无属性+仅一个div子节点”的div才会被替换,带属性的div(比如示例里的
style="width:80px")会被保留 - 额外的空div清理步骤可以移除那些完全没有内容的“空容器”,让HTML更干净
内容的提问来源于stack exchange,提问作者DaveTheAl
相关产品推荐
相关产品推荐

