Как я могу анализировать HTML с помощью html5lib и запрашивать анализируемый HTML с помощью XPath?
Я пытаюсь использовать html5lib для разбора html-страницы в том, что я могу запросить с помощью xpath. html5lib имеет почти нулевую документацию, и я потратил слишком много времени, пытаясь понять эту проблему. Конечная цель - вытащить вторую строку таблицы:
<html>
<table>
<tr><td>Header</td></tr>
<tr><td>Want This</td></tr>
</table>
</html>
поэтому попробуйте:
>>> doc = html5lib.parse('<html><table><tr><td>Header</td></tr><tr><td>Want This</td> </tr></table></html>', treebuilder='lxml')
>>> doc
<lxml.etree._ElementTree object at 0x1a1c290>
который выглядит хорошо, давайте посмотрим, что еще у нас есть:
>>> root = doc.getroot()
>>> print(lxml.etree.tostring(root))
<html:html xmlns:html="http://www.w3.org/1999/xhtml"><html:head/><html:body><html:table><html:tbody><html:tr><html:td>Header</html:td></html:tr><html:tr><html:td>Want This</html:td></html:tr></html:tbody></html:table></html:body></html:html>
LOL WUT?
серьезно. Я планировал использовать некоторый xpath для получения данных, которые я хочу, но это, похоже, не работает. Так что я могу сделать? Я готов попробовать разные библиотеки и подходы.
Ответы
Ответ 1
Отсутствие документации - хорошая причина избежать библиотеки IMO, как бы ни крути она была. Вы привязаны к использованию html5lib? Вы посмотрели на lxml.html?
Вот способ сделать это с помощью lxml:
from lxml import html
tree = html.fromstring(text)
[td.text for td in tree.xpath("//td")]
Результат:
['Header', 'Want This']
Ответ 2
То, что вы хотите использовать, - это аргумент namespaceHTMLElements
, который по умолчанию по умолчанию имеет значение True.
doc = html5lib.parse('''<html>
<table>
<tr><td>Header</td></tr>
<tr><td>Want This</td></tr>
</table>
</html>
''', treebuilder='lxml', namespaceHTMLElements=False)
print lxml.html.tostring(doc)
Однако, вероятно, проще использовать lxml.html.
Ответ 3
Я всегда рекомендую попробовать библиотеку lxml
. Это невероятно быстро и имеет множество функций.
Он также поддерживает парсер html5lib, если вам это нужно: html5parser
>>> from lxml.html import fromstring, tostring
>>> html = """
... <html>
... <table>
... <tr><td>Header</td></tr>
... <tr><td>Want This</td></tr>
... </table>
... </html>
... """
>>> doc = fromstring(html)
>>> tr = doc.cssselect('table tr')[1]
>>> print tostring(tr)
<tr><td>Want This</td></tr>
Ответ 4
С BeautifulSoup вы можете сделать это со
>>> soup = BeautifulSoup.BeautifulSoup('<html><table><tr><td>Header</td></tr><tr><td>Want This</td></tr></table></html>')
>>> soup.findAll('td')[1].string
u'Want This'
>>> soup.findAll('tr')[1].td.string
u'Want This'
(Очевидно, что действительно грубый пример, но ya.)
Ответ 5
Я считаю, что вы можете выполнить поиск css на объектах lxml.. так
elements = root.cssselect('div.content')
data = elements[0].text
Ответ 6
Так как html5lib (по умолчанию) создает деревья, содержащие (правильную) информацию о пространстве имен, которые вы указали (правые) пространства имен в ваших запросах.
Пример с запросом XPath:
import html5lib
inp='''<html>
<table>
<tr><td>Header</td></tr>
<tr><td>Want This</td></tr>
</table>
</html>'''
xns = '{http://www.w3.org/1999/xhtml}'
d = html5lib.parse(inp)
s = d.findall('.//{}td'.format(xns))[-1].text
print(s)
Вывод:
Want This
Тот же результат без XPath:
s = d.find(xns+'body').find(xns+'table').find(xns+'tbody') \
.findall(xns+'tr')[-1].find(xns+'td').text
В качестве альтернативы вы также можете сообщить html5lib, чтобы не добавлять информацию о пространстве имен во время разбора:
d = html5lib.parse(inp, namespaceHTMLElements=False)
s = d.findall('.//td')[-1].text
print(s)
Вывод:
Want This
Ответ 7
попробуйте использовать jquery. и вы можете получить все элементы. поочередно, вы можете поместить идентификатор в свою строку и вытащить его.
1)......
$( "td" ) [1].innerHTML будет тем, что вы хотите
2)......
$( "# blah" ). text() будет тем, что вы хотите