Эквивалентно InnerHTML при использовании lxml.html для анализа HTML
Я работаю над script с помощью lxml.html для анализа веб-страниц. В свое время я немного поработал над BeautifulSoup, но теперь я экспериментирую с lxml из-за его скорости.
Я хотел бы знать, какой самый разумный способ в библиотеке - сделать эквивалент Javascript InnerHtml - то есть получить или установить полное содержимое тега.
<body>
<h1>A title</h1>
<p>Some text</p>
</body>
InnerHtml:
<h1>A title</h1>
<p>Some text</p>
Я могу сделать это с помощью хаков (преобразование в строку/регулярные выражения и т.д.), но я предполагаю, что есть правильный способ сделать это, используя библиотеку, которую я пропускаю из-за незнания. Спасибо за любую помощь.
EDIT: Благодаря pobk за то, что он показал мне путь к этому так быстро и эффективно. Для тех, кто пытается то же самое, вот что я в итоге:
from lxml import html
from cStringIO import StringIO
t = html.parse(StringIO(
"""<body>
<h1>A title</h1>
<p>Some text</p>
Untagged text
<p>
Unclosed p tag
</body>"""))
root = t.getroot()
body = root.body
print (element.text or '') + ''.join([html.tostring(child) for child in body.iterdescendants()])
Обратите внимание, что синтаксический анализатор lxml.html фиксирует незакрытый тег, поэтому будьте осторожны, если это проблема.
Ответы
Ответ 1
Вы можете получить дочерние элементы ElementTree node с помощью методов getchildren() или iterdescendants() корня node:
>>> from lxml import etree
>>> from cStringIO import StringIO
>>> t = etree.parse(StringIO("""<body>
... <h1>A title</h1>
... <p>Some text</p>
... </body>"""))
>>> root = t.getroot()
>>> for child in root.iterdescendants(),:
... print etree.tostring(child)
...
<h1>A title</h1>
<p>Some text</p>
Это может быть сокращено следующим образом:
print ''.join([etree.tostring(child) for child in root.iterdescendants()])
Ответ 2
Извините за то, что вы снова это сделали, но я искал решение, и у вас есть ошибка:
<body>This text is ignored
<h1>Title</h1><p>Some text</p></body>
Текст непосредственно под корневым элементом игнорируется. Я закончил это:
(body.text or '') +\
''.join([html.tostring(child) for child in body.iterchildren()])
Ответ 3
import lxml.etree as ET
body = t.xpath("//body");
for tag in body:
h = html.fromstring( ET.tostring(tag[0]) ).xpath("//h1");
p = html.fromstring( ET.tostring(tag[1]) ).xpath("//p");
htext = h[0].text_content();
ptext = h[0].text_content();
вы также можете использовать .get('href')
для тега и .attrib
для атрибута,
здесь тег no жестко закодирован, но вы также можете сделать эту динамическую