【问题标题】:"has:()" and "not:()" pseudo-classes behaves otherwise when used within BeautifulSoup“has:()”和“not:()”伪类在 BeautifulSoup 中使用时表现不同
【发布时间】:2019-11-09 12:04:43
【问题描述】:

我试图弄清楚css pseudo-classesnot:()has:() 在以下情况下的工作方式。

以下选择器不应该打印27A-TAX DISTRICT 27A,但它会打印它:

from bs4 import BeautifulSoup

htmlelement = """
<tbody>
  <tr style="">
     <td><a>27A-TAX DISTRICT</a> 27A</td>
  </tr>

  <tr style="">
     <td><strong>Parcel Number</strong> 720</td>
  </tr>
</tbody>
"""
soup = BeautifulSoup(htmlelement,"lxml")
item = soup.select_one("tr:not(a)").text
print(item)

另一方面,下面的选择器应该打印I should be printed,但它会抛出AttributeError 错误。

from bs4 import BeautifulSoup

htmlelement = """
<p class="vital">I should be printed</p>
<p>I should not be printed</p>
"""
soup = BeautifulSoup(htmlelement,"lxml")
item = soup.select_one("p:has(.vital)").text
print(item)

我哪里出错了,我怎样才能让它们发挥作用?

【问题讨论】:

  • 我不认为它是重复的
  • 如果您认为这篇文章是重复的,那么您应该知道我的脚本行为不正确的原因@Zaraki Kenpachi。那是什么?
  • 这不是重复的。用户只是询问对:has():not() 的操作方式存在误解。混淆是由于对 :has():not() 实际运作方式的误解,我在下面的答案中已经解决了这一点。

标签: python python-3.x beautifulsoup css-selectors


【解决方案1】:

很遗憾,您对 :not():has() 所做的事情的理解很可能不正确。

在您的第一个示例中,您使用:

soup.select_one("tr:not(a)").text

您使用它的方式将选择每个tr。这是因为它说“我想要一个不是a 标记的tr 标记。tr 标记永远不是a 标记,因此您的代码总是抓取任何tr 标记的文本,包括那个包含27A-TAX DISTRICT

如果您想要没有a 标签的tr 标签,那么您可以使用:

soup.select_one("tr:not(:has(a))").text

这句话的意思是“我想要一个没有后代a 标记的tr 标记”。

更多信息请阅读:


这就引出了您的第二个问题。 :has() 是一个关系选择器。在您的第二个示例中,您使用了:

soup.select_one("p:has(.vital)").text

:has() 向前查看子代、后代或兄弟姐妹(取决于您使用的语法)以确定标签是否是您想要的标签。

所以你说的是“我想要一个p 标签,它有一个带有vital 类的后代标签”。您的p 标签甚至都没有后代,因此不可能有vital 类。你想要的其实更简单:

soup.select_one("p.vital").text

这句话的意思是“我想要一个p 标签,它也有一个vital 类。”

更多信息请阅读:

【讨论】:

  • 是的,看来我弄错了。所以:has() 在有孩子或兄弟姐妹的情况下有效。顺便说一句,:contains() 只查找文本或字符串,但不查找标记、ID、类等,对吗?感谢@facelessuser 让事情变得清晰。
  • :has() 行为根据前导组合子而改变::has(+ tag) 下一个兄弟,:has(&gt; tag) 是任何后代等等。:contains() 搜索给定标签下的文本(包括文本任何子标签)。它不看属性。为此,您需要使用属性选择器:facelessuser.github.io/soupsieve/selectors/#attribute-selectors.
猜你喜欢
  • 2011-03-05
  • 2022-11-29
  • 2022-01-15
  • 1970-01-01
  • 2022-10-08
  • 1970-01-01
  • 2018-02-07
  • 2020-10-15
  • 1970-01-01
相关资源
最近更新 更多