仅当有两个类并共享相同的第一个类时才选择元素

Posted

技术标签:

【中文标题】仅当有两个类并共享相同的第一个类时才选择元素【英文标题】:Selecting elements only if have two classes and share the same first one 【发布时间】:2016-12-30 13:32:02 【问题描述】:

我在要解析的 html 中有这些元素:

<td class="line"> GARBAGE </td>
<td class="line text"> I WANT THAT </td>
<td class="line heading"> I WANT THAT </td>
<td class="line"> GARBAGE </td>

如何制作一个 CSS 选择器来选择具有属性类行和其他类的元素(可能是标题、文本或其他任何东西)但不是仅属性类行?

我试过了:

 td[class=line.*]
 td.line.*
 td[class^=line.]

编辑

我正在使用 Python 和 BeautifulSoup:

url = 'http://www.somewebsite'
res = requests.get(url)
res.raise_for_status()
DicoSoup = bs4.BeautifulSoup(res.text, "lxml")
elems = DicoSoup.select('body div#someid tr td.line')

我正在考虑修改最后一部分,即 td.line 到 td.line.whateverotherclass 之类的东西(但不是单独的 td.line,否则我的选择器已经足够了)

【问题讨论】:

【参考方案1】:

@BoltClock suggested 通常是解决 CSS 选择器问题的正确方法。唯一的问题是BeautifulSoup supports a limited number of CSS selectors。例如,not() selector is :not(.supported) at the moment。

您可以使用“starts-with”选择器来检查一个类是否以line 开头,后跟一个空格(它非常脆弱,但适用于您的示例数据):

for td in soup.select("td[class^='line ']"):
    print(td.get_text(strip=True))

或者,您可以使用 find_all() 并使用 searching function 检查 class 属性以拥有 line 和其他一些类来解决它:

from bs4 import BeautifulSoup

data = """
<table>
    <tr>
        <td class="line"> GARBAGE </td>
        <td class="line text"> I WANT THAT </td>
        <td class="line heading"> I WANT THAT </td>
        <td class="line"> GARBAGE </td>
    </tr>
</table>"""
soup = BeautifulSoup(data, 'html.parser')

for td in soup.find_all(lambda tag: tag and tag.name == "td" and
                                    "class" in tag.attrs and "line" in tag["class"] and
                                    len(tag["class"]) > 1):
    print(td.get_text(strip=True))

打印:

I WANT THAT
I WANT THAT

【讨论】:

我应该编写什么 lambda 函数来获取子标签,其方式与以下代码行相同:DicoSoup.select('body div#somed tr td') @MthClv 你可以先找到父div,例如:div = soup.select_one("body div#somed"),然后在使用搜索搜索td 元素时使用div 变量而不是soup功能?有点像特定于上下文的搜索。 我需要结合属性类上的两个条件并更改祖先div的id(我写了一些id) 好主意!会做。再次感谢【参考方案2】:

您可以为类选择器链接 CSS 类。

.line 
  color: green;

.line.text 
  color: red;

.line.heading 
  color: blue;
<p class="line">GARBAGE</p>
<p class="line text">I WANT THAT</p>
<p class="line heading">I WANT THAT</p>
<p class="line">GARBAGE</p>

【讨论】:

我认为关键是要有 一个 选择器...而不是多个选择器。我不确定这是否可能 正确的 Paulie,我正在寻找一种方法将其包装在一个选择器中;类似 td.line.whateverOtherClass 对不起,我应该提过:我想在 Python 中使用 BeautifulSoup 库来做这件事,我以为我只是遗漏了一段关于 CSS 选择器的语法,它适用于所有程序

以上是关于仅当有两个类并共享相同的第一个类时才选择元素的主要内容,如果未能解决你的问题,请参考以下文章

仅当父元素具有特定类时才为列表项元素设置样式[重复]

仅当存在集合类而不是其他类时才应用 CSS 规则 [重复]

仅当有要展示的特色产品时才包含自定义 slideshow.php

仅当有数据时才呈现表

Javascript:仅当它是文本的第一个单词时才替换“x”,而不是其他任何地方

Firestore:仅当有更新时才从服务器获取数据,否则从缓存中获取