使用lxml.html解析HTML时,相当于InnerHTML

时间:2011-05-25 10:56:44

标签: python parsing lxml

我正在使用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>

我可以使用黑客(转换为字符串/正则表达式等)来做到这一点,但我假设有一个正确的方法来使用由于不熟悉我缺少的库。谢谢你的帮助。

编辑:感谢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解析器将修复未关闭的标记,因此请注意这是否有问题。

4 个答案:

答案 0 :(得分:15)

很抱歉再次提出这个问题,但我一直在寻找解决方案,而你的问题包含一个错误:

<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()])

答案 1 :(得分:10)

您可以使用根节点的getchildren()或iterdescendants()方法获取ElementTree节点的子节点:

>>> 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 :(得分:4)

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作为属性,

此处标签号是硬编码的,但您也可以执行此动态

答案 3 :(得分:0)

这是Python 3版本:

from xml.sax import saxutils
from lxml import html

def inner_html(tree):
    """ Return inner HTML of lxml element """
    return (saxutils.escape(tree.text) if tree.text else '') + \
        ''.join([html.tostring(child, encoding=str) for child in tree.iterchildren()])

请注意,这包括按andreymal的建议转义初始文本-如果您使用的是经过处理的HTML,则需要这样做以避免标记注入!