Поиск элемента html с классом с помощью lxml
Я искал всюду, и я больше всего нашел 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)
Он просто печатает пустой список.
Изменить:
Как странно. Я использовал Google в качестве тестовой страницы, и она отлично работает там, но она не работает на странице, которую я использовал (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)
Ответы
Ответ 1
На странице TopGear, которую вы используете для тестирования, нет никаких элементов <div class="channel">
. Но это работает (например):
el = doc.xpath("//div[@class='channel-title-container']")
Или это:
el = doc.xpath("//div[@class='a yb xr']")
Чтобы найти элементы <div>
с атрибутом class
, который содержит строку channel
, вы можете использовать
el = doc.xpath("//div[contains(@class, 'channel')]")
Ответ 2
Вы можете использовать lxml.cssselect для упрощения class
и id
запроса: 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 (* классы)
def _hasaclass(context, *cls):
return "your implementation ..."
xpath_utils = etree.FunctionNamespace(None)
xpath_utils['hasaclass'] = _hasaclass
el = doc.xpath("//div[hasaclass('channel')]")