示例:
html = <a><b>Text</b>Text2</a>
BeautifullSoup代码
[x.extract() for x in html.findAll(.//b)]
退出时我们有:
html = <a>Text2</a>
Lxml代码:
[bad.getparent().remove(bad) for bad in html.xpath(".//b")]
退出时我们有:
html = <a></a>
因为lxml认为&#34; Text2&#34;它是<b></b>
如果我们只需要连接标签的文字行,我们就可以使用:
for bad in raw.xpath(xpath_search):
bad.text = ''
但是,如何在不更改文本的情况下执行此操作,但删除没有尾部的标记?
答案 0 :(得分:6)
虽然phlou接受的答案可行,但有更简单的方法可以在不删除标签的情况下删除标签。
如果要删除特定元素,那么您要查找的LXML方法是drop_tree
。
来自文档:
删除元素及其所有子元素。与el.getparent()。remove(el)不同,这不会删除尾部文本;使用drop_tree,尾部文本与前一个元素合并。
如果您要删除特定代码的所有实例,可以使用lxml.etree.strip_elements
或lxml.html.etree.strip_elements
withtails=False
。
使用树或提供的标记名称删除所有元素 子树。这将删除元素及其整个子树, 包括他们的所有属性,文本内容和后代。它 除非你,否则也将删除元素的尾部文本 将
with_tail
关键字参数选项显式设置为False。
所以,对于原帖中的例子:
>>> from lxml.html import fragment_fromstring, tostring
>>>
>>> html = fragment_fromstring('<a><b>Text</b>Text2</a>')
>>> for bad in html.xpath('.//b'):
... bad.drop_tag()
>>> tostring(html)
'<a>Text2</a>'
或
>>> from lxml.html import fragment_fromstring, tostring, etree
>>>
>>> html = fragment_fromstring('<a><b>Text</b>Text2</a>')
>>> etree.strip_elements(html, 'b', with_tail=False)
>>> tostring(html)
'<a>Text2</a>'
答案 1 :(得分:4)
我执行了以下操作以将尾部文本保护到上一个兄弟或父母。
def remove_keeping_tail(self, element):
"""Safe the tail text and then delete the element"""
self._preserve_tail_before_delete(element)
element.getparent().remove(element)
def _preserve_tail_before_delete(self, node):
if node.tail: # preserve the tail
previous = node.getprevious()
if previous is not None: # if there is a previous sibling it will get the tail
if previous.tail is None:
previous.tail = node.tail
else:
previous.tail = previous.tail + node.tail
else: # The parent get the tail as text
parent = node.getparent()
if parent.text is None:
parent.text = node.tail
else:
parent.text = parent.text + node.tail
HTH