Эквивалентно InnerHTML при использовании lxml.html для разбора HTML - PullRequest
22 голосов
/ 25 мая 2011

Я работаю над сценарием, использующим lxml.html для разбора веб-страниц. В свое время я сделал немало BeautifulSoup, но сейчас экспериментирую с lxml из-за его скорости.

Я хотел бы знать, какой самый разумный способ в библиотеке - сделать эквивалент InnerHtml в Javascript, то есть получить или установить полное содержимое тега.

<body>
<h1>A title</h1>
<p>Some text</p>
</body>

InnerHtml поэтому:

<h1>A title</h1>
<p>Some text</p>

Я могу сделать это, используя хаки (преобразование в строку / регулярные выражения и т. Д.), Но я предполагаю, что есть правильный способ сделать это, используя библиотеку, которую мне не хватает из-за незнакомости. Спасибо за любую помощь.

РЕДАКТИРОВАТЬ: Спасибо побк за то, что показал мне путь к этому так быстро и эффективно. Для тех, кто пытается сделать то же самое, вот что я закончил:

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 исправит незамкнутый тег, поэтому будьте осторожны, если это проблема.

Ответы [ 3 ]

15 голосов
/ 18 июня 2011

Извините, что снова поднял этот вопрос, но я искал решение, и у вас есть ошибка:

<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()])
10 голосов
/ 25 мая 2011

Вы можете получить дочерние элементы узла ElementTree, используя методы корневого узла getchildren () или iterdescendants ():

>>> 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()])
4 голосов
/ 16 января 2015
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 жестко закодирован, но вы также можете сделать эту динамическую

...