带有 :not 的 CSS 选择器未按预期运行

Posted

技术标签:

【中文标题】带有 :not 的 CSS 选择器未按预期运行【英文标题】:CSS selector with :not does not behave as expected 【发布时间】:2019-11-16 11:56:43 【问题描述】:
<p class="p_cat_heading">SOUND WORD</p>
<p class="p_normal__and__avoid_page_break_after"><span class="c_tone_char">Vene</span><span class="c_tone_char__and__underline">zue</span><span class="c_tone_char">la</span> /<span class="calibre22">venedswela</span>/</p>
<p class="p_normal__and__avoid_page_break_after">South American country over the equator, known in part for its sunny beaches. Pronounce it in Italian for a better sound match.</p>
<p class="p_normal__and__avoid_page_break_after"><img   src="../images/00461.jpeg" class="calibre18"/></p>
<p class="p_cat_heading__and__centre_alignment">COMPONENTS</p>

我正在使用以下 CSS 选择器:

content = str(soup.select_one('.p_cat_heading:contains("SOUND WORD") + :not(.p_cat_heading)'))  # type: str

这应该选择所有直到具有类 p_cat_heading 的元素。但是它只选择:

<p class="p_normal__and__avoid_page_break_after"><span class="c_tone_char">Vene</span><span class="c_tone_char__and__underline">zue</span><span class="c_tone_char">la</span> /<span class="calibre22">venedswela</span>/</p>

我一定误解了 CSS 选择器的工作原理。我认为: 像 Python 切片一样工作,但似乎并非如此。也就是说,我不确定我错过了什么。

【问题讨论】:

select替换select_one 这不是 CSS 中 + 运算符的工作方式。 selector1 + selector2 匹配匹配 selector2 的元素,该元素紧跟在匹配 selector1 的元素之后。它与中间的所有元素都不匹配。 @abdusco - 试一试,但它不起作用 @Barmar 啊,这就解释了!那么有没有一种语法可以让你在两者之间获得一切? 我不这么认为。 【参考方案1】:

感谢@Barmar 在这方面的帮助。重申他的评论,您不能使用 CSS 选择器来执行此操作。相反,我所做的是遍历元素直到到达分隔符:

for temp_heading in heading.find_next_siblings():
    if temp_heading.attrs["class"][0] == "p_cat_heading":
        break
    else:
        print(str(temp_heading))
organized_entry["soundword"] = content

其中 temp_heading 是 bs.element.Tag 的一个实例,它从指向开始:

<p class="p_cat_heading">SOUND WORD</p>

【讨论】:

【参考方案2】:

如果如您所见,您可以使用过滤并从第一个搜索字符串的同级 p 标签中过滤掉作为第二个搜索字符串或以下同级的 p 标签。这是非常具体的,以匹配您所展示的内容。

from bs4 import BeautifulSoup as bs

html = '''
<html>
 <head></head>
 <body>
  <p class="p_cat_heading">SOUND WORD</p> 
  <p class="p_normal__and__avoid_page_break_after"><span class="c_tone_char">Vene</span><span class="c_tone_char__and__underline">zue</span><span class="c_tone_char">la</span> /<span class="calibre22">venedswela</span>/</p> 
  <p class="p_normal__and__avoid_page_break_after">South American country over the equator, known in part for its sunny beaches. Pronounce it in Italian for a better sound match.</p> 
  <p class="p_normal__and__avoid_page_break_after"><img   src="../images/00461.jpeg" class="calibre18"></p> 
  <p class="p_cat_heading__and__centre_alignment">COMPONENTS</p>
 </body>
</html>
'''
soup = bs(html, 'lxml')
result = [item.text.strip() for item in soup.select('p:contains("SOUND WORD") ~ p:not(p:contains("COMPONENTS") ~ p, p:contains("COMPONENTS"))')]

【讨论】:

以上是关于带有 :not 的 CSS 选择器未按预期运行的主要内容,如果未能解决你的问题,请参考以下文章

迭代器未按预期运行

Sendgrid 替换包装器未按预期工作

CSS选择器级联/特异性未按预期工作

CSS 规则未按预期应用

SQL NOT EXISTS 子查询未按预期运行

联系人选择器未在 Android Studio 中提供预期结果