使用lxml.html解析HTML时相当于InnerHTML的内容是什么

33 投票
5 回答
18984 浏览
提问于 2025-04-16 18:18

我正在用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解析器会自动修复未闭合的标签,所以如果这对你来说是个问题,要小心哦。

5 个回答

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 来获取属性。

这里的标签编号是写死的,但你也可以让它变得动态,也就是说可以根据需要来改变。

16

抱歉再次提起这个问题,但我一直在寻找解决办法,你的方案里有个错误:

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

你可以通过根节点的 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()])

撰写回答