使用lxml.html解析HTML时相当于InnerHTML的内容是什么
我正在用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()])