正则表达式捕获带有类名的 html 元素
Posted
技术标签:
【中文标题】正则表达式捕获带有类名的 html 元素【英文标题】:Regex to capture html elements with their class name 【发布时间】:2020-06-03 21:47:01 【问题描述】:我正在尝试使用 python 获取 html 文件中所有元素的元素和类名。我设法使用下面的代码获取所有类名。之所以这样写,是因为我会在存储带有类名的元素时浏览大量 html 文件。忽略没有类名的元素。
temp_file = open(root + "/" + file, "r", encoding="utf-8-sig", errors="ignore")
temp_content = temp_file.read()
class_names = re.findall("class=\"(.*?)\"", temp_content)
但是现在我正在努力寻找一种方法来获取该类所属的元素。请记住,元素有时会相互重叠,因此 readlines() 也无济于事,而且可能比一次正则表达式整个文档要慢。
<div class="header_container container_12">
<div class="grid_5">
<h1><a href="#">Logo Text Here</a></h1>
</div>
<div class="grid_7">
<div class="menu_items">
<a href="#" class="home active">Home</a><a href="#" class="portfolio">Portfolio</a>
<a href="#"
class="about">About Me
</a><a href="#" class="contact">Contact Me</a>
</div>
</div>
</div>
上面的 html sn-p 故意缩进严重,以展示我正在使用的数据类型...... 目标可能是将它们存储在哈希图中。 即
"header_Container container_12": "div"
"grid_5": "div"
"grid_7": "div"
"menu_items": "div"
"home active": "a"
"portfolio": "a"
"about": "a"
"contact": "a"
【问题讨论】:
你考虑过解析 DOM 吗? Parsing HTML with regex is a hard job HTML 和正则表达式不是好朋友。使用解析器,它更简单、更快且更易于维护。 【参考方案1】:正则表达式对于 HTML 解析来说是一个糟糕的选择,但幸运的是,这对于 BeautifulSoup 来说是微不足道的:
from bs4 import BeautifulSoup
html = """<div class="header_container container_12">
<div class="grid_5">
<h1><a href="#">Logo Text Here</a></h1>
</div>
<div class="grid_7">
<div class="menu_items">
<a href="#" class="home active">Home</a><a href="#" class="portfolio">Portfolio</a>
<a href="#"
class="about">About Me
</a><a href="#" class="contact">Contact Me</a>
</div>
</div>
</div>"""
for elem in BeautifulSoup(html, "lxml").find_all(attrs="class": True):
print(elem.attrs["class"], elem.name)
输出:
['header_container', 'container_12'] div
['grid_5'] div
['grid_7'] div
['menu_items'] div
['home', 'active'] a
['portfolio'] a
['about'] a
['contact'] a
您可以根据需要将其放入 dict 中,但要小心,因为多个元素可能会映射到每个存储桶。它只会告诉你一个元素存在并且有一个特定的标签名,给定一个特定的类名字符串或特定顺序的元组。
elems =
for elem in BeautifulSoup(html, "lxml").find_all(attrs="class": True):
elems[tuple(elem.attrs["class"])] = elem.name
for k, v in elems.items():
print(k, v)
【讨论】:
感谢您的解决方案,不得不切换到“html.parser”,因为它无法找到“lxml”。作为一个附带问题,是否有一种简单的方法可以使用漂亮的汤来获取哪些元素?因此,在上面的 html 中,将“header_container”作为所有其他元素的父元素,将“menu_items”作为“a”元素的父元素。 当然,请参阅finding elements by class name 和finding children of a node。【参考方案2】:我认为 regex 是不适合这里工作的工具,请考虑将 HTML 加载到 DOM 文档中并改用 DOM 选择器对其进行解析。
以下示例是 javascript,因为它允许我将其作为可运行的 sn-p 包含在内 - 但它应该足以解释该方法,以便您创建等效的 python。
var classElements = document.querySelectorAll("[class]");
for(i = 0; i < classElements.length; i++)
console.log(classElements[i].className + ": " + classElements[i].tagName);
<div class="header_container container_12">
<div class="grid_5">
<h1><a href="#">Logo Text Here</a></h1>
</div>
<div class="grid_7">
<div class="menu_items">
<a href="#" class="home active">Home</a><a href="#" class="portfolio">Portfolio</a>
<a href="#"
class="about">About Me
</a><a href="#" class="contact">Contact Me</a>
</div>
</div>
【讨论】:
以上是关于正则表达式捕获带有类名的 html 元素的主要内容,如果未能解决你的问题,请参考以下文章
我可以使用哪种正则表达式条件来捕获具有 R 中单位的数学公式?
带有正则表达式捕获的 NSPredicate 总是得到 0 个结果