1

我在用 div 包装图像时遇到问题。

from lxml.html import fromstring
from lxml import etree

tree = fromstring('<img src="/img.png"/> some text')
div = etree.Element('div')
div.insert(0, tree.find('img'))
tree.insert(0, div)
print etree.tostring(tree)

<span><div><img src="/img.png"/> some text</div></span>

为什么它会添加一个跨度,我怎样才能让它在没有文本的情况下包装图像?

4

2 回答 2

3

因为lxml实际上是一个 xml 解析器。它有一些宽容的解析规则,允许它解析 html(lxml.html部分),但它会在内部始终构建一个有效的树。

'<img src="/img.png"/> some text'不是树,因为它没有单个根元素,只有一个img元素和一个文本节点。为了能够在内部存储这个片段,lxml 需要将它包装在一个合适的标签中。如果你单独给它一个字符串,它会将它包装在一个p标签中。早期版本只是将所有内容都包装在html标签中,这可能会导致更多混乱。

您也可以使用html.fragment_fromstring,在这种情况下不会添加标签,但会因为片段无效而引发错误。

至于为什么文本会粘在img标签上:这就是 lxml 存储文本的方式。举个例子:

>>> p = html.fromstring("<p>spam<br />eggs</p>")
>>> br = p.find("br")
>>> p.text
'spam'
>>> br.text       # empty
>>> br.tail       # this is where text that comes after a tag is stored
'eggs'

所以通过移动标签,你也移动了它的尾巴。

于 2013-07-17T22:44:34.250 回答
1

lxml.html 是一个更友好、更温和的 xml 处理器,它试图理解无效的 xml。从 xml 的角度来看,您传入的刺痛只是垃圾,但 lxml.html 将其包装在 span 元素中以使其再次有效。如果您不希望 lxml.html 猜测,请坚持使用 lxml.etree.fromstring()。该版本将拒绝该字符串。

于 2013-07-17T22:37:59.570 回答