Python:使用 `lxml.html` 向标签注入 HTML 内容

12 投票
3 回答
5053 浏览
提问于 2025-04-16 23:24

我正在使用 lxml.html 这个库来解析一个 HTML 文档。

我找到了一个特定的标签,我称之为 content_tag,我想要改变它的内容(也就是在 <div></div> 之间的文本),新的内容是一个包含一些 HTML 的字符串,比如说是 'Hello <b>world!</b>'

我该怎么做呢?我试过用 content_tag.text = 'Hello <b>world!</b>',但这样会把所有的 HTML 标签都转义了,把 < 替换成 &lt; 等等。

我想要插入文本时 转义任何 HTML。那我该怎么做呢?

3 个回答

0

经过一番尝试,我找到了这个解决办法:

fragments = lxml.html.fragments_fromstring(<string with tags to inject>)
last = None

for frag in fragments:
  if isinstance(frag, lxml.etree._Element):
    content_tag.append(frag)
    last = frag
  else:
    if last:
      last.tail = frag
    else:
      content_tag.text = frag
0

假设content_tag里面没有任何子元素,你可以直接这样做:

from lxml import html
from lxml.html.builder import B

...

content_tag.text = 'Hello '
content_tag.append(B('world!'))
print html.tostring(content_tag)
8

这是一种方法:

#!/usr/bin/env python2.6
from lxml.html import fromstring, tostring
from lxml.html import builder as E
fragment = """\
<div id="outer">
  <div id="inner">This is div.</div>
</div>"""

div = fromstring(fragment)
print tostring(div)
# <div id="outer">
#   <div id="inner">This is div.</div>
# </div>
div.replace(div.get_element_by_id('inner'), E.DIV('Hello ', E.B('world!')))
print tostring(div)
# <div id="outer">
#   <div>Hello <b>world!</b></div></div>

另请参见:http://lxml.de/lxmlhtml.html#creating-html-with-the-e-factory

补充:我应该早点承认,我对lxml并不是很熟悉。我简单看了一下文档和源代码,但没找到一个很好的解决方案。也许会有更熟悉的人过来帮我们解答。

在此期间,这个方法似乎可以用,但测试得不够充分:

import lxml.html
content_tag = lxml.html.fromstring('<div>Goodbye.</div>')
content_tag.text = '' # assumes only text to start
for elem in lxml.html.fragments_fromstring('Hello <b>world!</b>'):
    if type(elem) == str: #but, only the first?
        content_tag.text += elem
    else:
        content_tag.append(elem)
print lxml.html.tostring(content_tag)

再次补充:这个版本会删除文本和子元素。

somehtml = 'Hello <b>world!</b>'
# purge element contents
content_tag.text = ''
for child in content_tag.getchildren():
    content_tag.remove(child)

fragments = lxml.html.fragments_fromstring(somehtml)
if type(fragments[0]) == str:
    content_tag.text = fragments.pop(0)
content_tag.extend(fragments)

撰写回答