【问题标题】:Finding html element with class using lxml使用lxml查找带有类的html元素
【发布时间】:2012-01-03 19:38:27
【问题描述】:

我到处搜索,我发现最多的是 doc.xpath('//element[@class="classname"]'),但无论我尝试什么都不起作用。

我正在使用的代码

import lxml.html

def check():
    data = urlopen('url').read();
    return str(data);

doc = lxml.html.document_fromstring(check())
el = doc.xpath("//div[@class='test']")
print(el)

它只是打印一个空列表。

编辑: 多么奇怪。我使用谷歌作为测试页面,它在那里工作正常,但它在我使用的页面上不起作用(youtube)

这是我正在使用的确切代码。

import lxml.html
from urllib.request import urlopen
import sys

def check():
    data = urlopen('http://www.youtube.com/user/TopGear').read(); #TopGear as a test
    return data.decode('utf-8', 'ignore');


doc = lxml.html.document_fromstring(check())
el = doc.xpath("//div[@class='channel']")
print(el)

【问题讨论】:

  • 'url' 是一个 3 个字符的字符串。它不是 HTML 文件。
  • 显然我这样做了,而不是发布真实的网址。
  • 请提供SSCCE

标签: class python-3.x lxml


【解决方案1】:

您用于测试的 TopGear 页面没有任何 <div class="channel"> 元素。但这有效(例如):

el = doc.xpath("//div[@class='channel-title-container']")

或者这个:

el = doc.xpath("//div[@class='a yb xr']")

要查找具有class 属性且包含字符串channel<div> 元素,您可以使用

el = doc.xpath("//div[contains(@class, 'channel')]") 

【讨论】:

  • branded-page channelchannel 不同。
  • 但是,根据 css,该元素有两个类,brand-page 和 channel。那为什么不呢?
  • 是的,根据 CSS 有两个类。但是 XPath 不知道 CSS 的规则。对于 XPath,branded-page channel 只是一个没有特殊含义的字符串。
  • 这真的很有帮助,谢谢。作为测试,我试图在此页面上获取一个元素,但它也不起作用。这真的开始让我生气了。 el = doc.xpath('//a[@class="vote-accepted-off"]') 好像不喜欢找没有子元素的元素。
  • 为了完成你的回答,我们也可以使用 not() 进行否定。例如:el = doc.xpath("//div[contains(@class, 'channel') and not(contains(@class, 'disabled'))]")
【解决方案2】:

您可以使用 lxml.cssselect 来简化 classid 请求:http://lxml.de/dev/cssselect.html

【讨论】:

    【解决方案3】:

    HTML 使用类(很多),这使得它们可以方便地挂钩 XPath 查询。然而,XPath 不了解/支持 CSS 类(甚至是空格分隔的列表),这使得检查类非常麻烦:查找具有特定类的元素的规范正确方法是:

    //*[contains(concat(' ', normalize-space(@class), ' '), '$className')]
    

    在你的情况下是

    el = doc.xpath(
        "//div[contains(concat(' ', normalize-space(@class), ' '), 'channel')]"
    )
    # print(el)
    # [<Element div at 0x7fa44e31ccc8>, <Element div at 0x7fa44e31c278>, <Element div at 0x7fa44e31cdb8>]
    

    或使用自己的 XPath 函数 hasclass(*classes)

    def _hasaclass(context, *cls):
        return "your implementation ..." 
    
    xpath_utils = etree.FunctionNamespace(None)
    xpath_utils['hasaclass'] = _hasaclass
    
    el = doc.xpath("//div[hasaclass('channel')]")
    

    【讨论】:

    • contains() 中的第二个参数也应该添加空格(如' $className '' channel ')。否则你仍然会匹配somechannel这样的类。
    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多