正则表达式捕获带有类名的 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 个结果

如何在正则表达式中使用带有字符的“环视”来捕获整个字符串?

Perl 中的正则表达式组:如何从正则表达式组中捕获与字符串中出现的未知数量/多个/变量匹配的元素到数组中?

js正则表达式替换捕获内容

c# 正则表达式捕获