Python、lxml及使用lxml.html.tostring(el)移除外部标签

5 投票
4 回答
2198 浏览
提问于 2025-04-17 13:02

我正在使用下面的代码来获取一个部分的所有HTML内容,以便保存到数据库中。

el = doc.get_element_by_id('productDescription')
lxml.html.tostring(el)

产品描述有一个标签,看起来像这样:

<div id='productDescription'>

     <THE HTML CODE I WANT>

</div>

这段代码运行得很好,能给我所有的HTML代码,但我该怎么去掉最外层的部分,也就是 <div id='productDescription'> 和结束标签 </div> 呢?

4 个回答

0

这里有一个函数,可以实现你想要的功能。

def strip_outer(xml):
    """
    >>> xml = '''<math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/1998/Math/MathML         http://www.w3.org/Math/XMLSchema/mathml2/mathml2.xsd">
    ...   <mrow>
    ...     <msup>
    ...       <mi>x</mi>
    ...       <mn>2</mn>
    ...     </msup>
    ...     <mo> + </mo>
    ...     <mi>x</mi>
    ...   </mrow>
    ... </math>'''
    >>> so = strip_outer(xml)
    >>> so.splitlines()[0]=='<mrow>'
    True

    """
    xml = xml.replace('xmlns=','xmlns:x=')#lxml fails with xmlns= attribute
    xml = '<root>\n'+xml+'\n</root>'#...and it can't strip the root element
    rx = lxml.etree.XML(xml)
    lxml.etree.strip_tags(rx,'math')#strip <math with all attributes
    uc=lxml.etree.tounicode(rx)
    uc=u'\n'.join(uc.splitlines()[1:-1])#remove temporary <root> again
    return uc.strip()
3

如果你的 productDescription 这个 div 里面包含了混合的文本和元素内容,比如:

<div id='productDescription'>
  the
  <b> html code </b>
  i want
</div>

你可以使用 xpath('node()') 来获取这些内容(以字符串的形式),方法是进行遍历:

s = ''
for node in el.xpath('node()'):
    if isinstance(node, basestring):
        s += node
    else:
        s += lxml.html.tostring(node, with_tail=False)
3

你可以把每个子元素单独转换成字符串:

text = el.text
text += ''.join(map(lxml.html.tostring, el.iterchildren()))

或者用一种更“黑科技”的方法:

el.attrib.clear()
el.tag = '|||'
text = lxml.html.tostring(el)
assert text.startswith('<'+el.tag+'>') and text.endswith('</'+el.tag+'>')
text = text[len('<'+el.tag+'>'):-len('</'+el.tag+'>')]

撰写回答