python lxml - 简单地获取/检查 HTML 元素的类

Posted

技术标签:

【中文标题】python lxml - 简单地获取/检查 HTML 元素的类【英文标题】:python lxml - simply get/check class of HTML element 【发布时间】:2017-01-27 08:24:00 【问题描述】:

我使用tree.xpath 遍历所有有趣的 html 元素,但我需要能够判断当前元素是否属于某个 CSS 类。

from lxml import html

mypage = """
<div class="otherclass exampleclass">some</div>
<div class="otherclass">things</div>
<div class="exampleclass">are</div>
<div class="otherclass">better</div>
<div>left</div>"""

tree = html.fromstring(mypage)

for item in tree.xpath( "//div" ):
  print("testing")
  #if "exampleclass" in item.getListOfClasses():
  #  print("foo")
  #else:
  #  print("bar")

整体结构应该保持不变。

检查当前div 是否具有exampleclass 类的快速方法是什么?

在上面的例子中,item 属于lxml.html.HtmlElement 类,它具有classes 属性,但我不明白这是什么意思:

课程 围绕“类”属性的类似集合的包装器。

获取方法:unreachable.classes(self) - 'class' 属性周围的类似集合的包装器。

设置方法:unreachable.classes(self, classes)

它返回一个lxml.html.Classes 对象,该对象有一个__iter__ 方法,结果iter() 有效。所以我构造了这段代码:

for item in tree.xpath( "//div" )
  match = False
  for classname in iter(item.classes):
    if classname == "exampleclass":
      match = True
  if match:
    print("foo")
  else:
    print("bar")

但我希望有更优雅的方法。

我尝试搜索类似的问题,但我发现的只是各种“我如何获取 'classname' 的所有元素”,但是我需要循环中的所有 divs,我只想区别对待其中一些。

【问题讨论】:

【参考方案1】:

你可以优雅地使用membership test operator in

for item in tree.xpath( "//div" ):
  if "exampleclass" in iter(item.classes):
    print("foo")

对于未定义 __contains__() 但定义的用户定义的类 如果 zx == z 的某些值是,则定义 __iter__()x in y 为真 在迭代 y 时产生。

【讨论】:

【参考方案2】:

不需要 iterif "exampleclass" in item.classes: 做同样的事情,只是效率更高。

from lxml import html

mypage = """
<div class="otherclass exampleclass">some</div>
<div class="otherclass">things</div>
<div class="exampleclass">are</div>
<div class="otherclass">better</div>
<div>left</div>"""

tree = html.fromstring(mypage)

for item in tree.xpath("//div"):
    if "exampleclass" in item.classes:
        print("foo")

不同之处在于在集合上调用 iter 会使查找线性化,因此绝对不是搜索集合的有效方法,这里差别不大,但在某些情况下会有巨大的差异:

In [1]: st = set(range(1000000))

In [2]: timeit 100000 in st
10000000 loops, best of 3: 51.4 ns per loop

In [3]: timeit 100000 in iter(st)
100 loops, best of 3: 1.82 ms per loop

你也可以通过 lxml 使用css selectors:

for item in tree.cssselect("div.exampleclass"):
    print("foo")

视情况而定,您也可以使用 contains:

for item in tree.xpath("//div[contains(@class, 'exampleclass')]"):
    print("foo")

【讨论】:

很好,谢谢。不过我不能使用选择器,因为我需要divs 循环中的类和不类,更新了示例代码,希望能更清楚。 xpath contains 在类 exampleclass-numbertwo 存在的情况下会出现问题,请参阅 ***.com/a/1604480/188159 @qubodup,是的,这就是我添加视情况而定的原因。您是在寻找不止一门课还是只找一门课?

以上是关于python lxml - 简单地获取/检查 HTML 元素的类的主要内容,如果未能解决你的问题,请参考以下文章

Python lxml包下面的xpath基本用法

python 检查两个lxml元素是否相等。

scrapy简单入门

学习笔记Python - Lxml

自学Python爬虫简单入门到进阶:正则表达式+lxml+requests+Beautiful Soup+基础

无法在 xpath 中获取文本(lxml/python)