Как я могу проанализировать 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 для получения нужных мне данных, но, похоже, это не сработало. Так что я могу сделать? Я готов попробовать разные библиотеки и подходы.
7 ответов
Недостаток документации - хороший повод избегать библиотеки IMO, какой бы крутой она ни была. Вы намерены использовать html5lib? Вы смотрели на lxml.html?
Вот способ сделать это с помощью lxml:
from lxml import html
tree = html.fromstring(text)
[td.text for td in tree.xpath("//td")]
Результат:
['Header', 'Want This']
То, что вы хотите использовать, это 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.
Я всегда рекомендую попробовать 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>
С 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'
(Очевидно, это очень грубый пример, но да.)
Так как 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)
Выход:
Хочу это
Тот же результат без 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)
Выход:
Хочу это
Я считаю, что вы можете сделать поиск CSS по объектам lxml.. как так
elements = root.cssselect('div.content')
data = elements[0].text
Попробуйте использовать jquery. и вы можете получить все элементы. поочередно, вы можете поставить id на свой ряд и вытащить его.
1)......
$ ("td") [1].innerHTML будет тем, что вы хотите
2)......
$ ("# бла").text() будет то, что вы хотите