【问题标题】:Remove elements from tree based on list of terms根据术语列表从树中删除元素
【发布时间】:2016-03-04 22:44:32
【问题描述】:

我正在尝试从网页(运行脚本时传递其 URL)中捕获一些文本,但它隐藏在没有分配其他属性的段落标记中。我可以收集每个段落标签的内容,但我想从树中删除包含任何关键字列表的任何元素。

我收到以下错误:

tree.remove(elem) TypeError: Argument 'element' has wrong type (预期 lxml.etree._Element,得到 _ElementStringResult)

我知道当我尝试遍历树时返回的是错误的类型,但是我该如何获取元素呢?

示例代码:

    #!/usr/bin/python

    from lxml import html
    from lxml import etree

    url = sys.argv[1]
    page = requests.get(url)
    tree = html.fromstring(page.content)

    terms = ['keyword1','keyword2','keyword3','keyword4','keyword5','keyword6','keyword7']
    paragraphs = tree.xpath('//p/text()')
    for elem in paragraphs:
        if any(term in elem for term in terms):
            tree.remove(elem) 

【问题讨论】:

标签: python html lxml


【解决方案1】:

在您的代码中,elem 是一个 _ElementStringResult,它具有实例方法 getparent。它的父节点是<p> 节点之一的Element 对象。

父级有一个remove 方法,可用于将其从树中移除:

element.getparent().remove(element)

我不相信有更直接的方法,对于为什么没有removeself 方法我也没有很好的答案。

使用示例html:

content = '''
<root>
    <p> nothing1 </p>
    <p> keyword1 </p>
    <p> nothing2 </p>
    <p> nothing3 </p>
    <p> keyword4 </p>
</root>
'''

您可以在代码中看到这一点:

from lxml import html
from lxml import etree

tree = html.fromstring(content)

terms = ['keyword1','keyword2','keyword3','keyword4','keyword5','keyword6','keyword7']
paragraphs = tree.xpath('//p/text()')
for elem in paragraphs:
    if any(term in elem for term in terms):
        actual_element = elem.getparent() 
        actual_element.getparent().remove(actual_element)

for child in tree.getchildren():
    print('<{tag}>{text}</{tag}>'.format(tag=child.tag, text=child.text))

# Output:
# <p> nothing1 </p>
# <p> nothing2 </p>
# <p> nothing3 </p>

从 cmets 看来,这段代码似乎不适合您。如果是这样,您可能需要提供有关 html 结构的更多信息。

【讨论】:

  • 我无法获得 _ElementStringResult 的父级,因为 getparent() 需要一个 _Element。
  • 我做到了,但解决方案带来了两个问题:首先,它抱怨 Element 不是节点的子节点,因为树中每个段落标签的父节点都是 "”,但它只捕获第一个单词。其次,这个例子只有在有一个段落标签的情况下才有效,但我要捕获所有这些,然后删除特定的。在此示例中,body 有效,因为只有一个 body,因此当您删除该元素时,其他任何内容都不会发生。但是如果我p.getparent().remove(p),它将删除所有段落元素。我该如何解决?
  • @user2912466 它不会删除所有元素,只会删除p
  • @user2912466 查看更新后的答案,我猜你需要拨打getparent 两次;第一次获取&lt;p&gt;节点,第二次获取其父节点。
猜你喜欢
  • 1970-01-01
  • 2017-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 2013-10-17
相关资源
最近更新 更多