web-dev-qa-db-ja.com

lxmlを使用してクラスでhtml要素を検索する

私はどこでも検索しましたが、最も見つけたのは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)
11
Vexx

テストに使用する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')]") 
27
mzjn

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')]")
1
Andrei.Danciuc

Lxml.cssselectを使用して、classおよびidリクエストを簡略化できます: http://lxml.de/dev/cssselect.html

1
dmzkrsk