【问题标题】:pulling multiple values from python ElementTree with lxml and xpath使用 lxml 和 xpath 从 python ElementTree 中提取多个值
【发布时间】:2013-05-24 15:04:57
【问题描述】:

我几乎可以肯定这样做是非常错误的,我的问题的原因是我自己的无知,但是阅读 python 文档和示例并没有帮助。

我正在网页抓取。我正在抓取的页面具有以下显着元素:

<div class='parent'>
   <span class='title'>
      <a>THIS IS THE TITLE</a>
   </span>
   <div class='copy'>
      <p>THIS IS THE COPY</p>
   </div>
</div>

我的目标是从 'title' 和 'copy' 中提取文本节点,按其父 div 分组。在上面的例子中,我想检索一个元组('THIS IS THE TITLE', 'THIS IS THE COPY')

下面是我的代码

## 'tree' is the ElementTree of the document I've just pulled 
xpath = "//div[@class='parent']"
filtered_html = tree.xpath(xpath)

arr = []

for i in filtered_html:

   title_filter = "//span[@class='author']/a/text()"  # xpath for title text
   copy_filter = "//div[@class='copy']/p/text()"      # xpath for copy text

   title = i.getroottree().xpath(title_filter)
   copy = i.getroottree().xpath(copy_filter)
   arr.append((title, copy))

我希望filtered_html 是一个 n 元素的列表(确实如此)。然后,我尝试遍历该元素列表,并为每个元素将其转换为 ElementTree 并检索标题并使用另一个 xpath 表达式复制文本。所以在每次迭代中,我希望title 是长度为 1 的列表,包含元素 i 的标题文本,而 copy 是复制文本的对应列表。

我最终得到的是:在每次迭代中,title 是一个长度为 n 的列表,其中包含文档中与 title_filter xpath 表达式匹配的所有元素,copy 是一个对应的复制文本的长度列表n

我敢肯定,到现在为止,任何知道他们在用 xpath 和 etree 做什么的人都可以认识到我在做一些可怕、错误和愚蠢的事情。如果是这样,他们能告诉我应该怎么做吗?

【问题讨论】:

    标签: python xpath lxml elementtree


    【解决方案1】:

    您的核心问题是,您对每个文本元素进行的 getroottree 调用会使您重置为在整个树上运行 xpath。 getroottree 就像它听起来的那样 - 返回您调用它的元素的根元素树。如果你离开那个呼唤,在我看来你会得到你想要的。

    我个人会在我的主循环的元素树上使用iterfind 方法,并且可能会在结果元素上使用findtext 方法以确保我只收到一个标题和一份副本。

    我的(未经测试!)代码如下所示:

    parent_div_xpath = "//div[@class='parent']"
    title_filter = "//span[@class='title']/a"
    copy_filter = "//div[@class='copy']/p"
    arr = [(i.findtext(title_filter), i.findtext(copy_filter)) for i in tree.iterfind(parent_div_xpath)]
    

    或者,您可以完全跳过显式迭代:

    title_filter = "//div[@class='parent']/span[@class='title']/a/text()"
    copy_filter = "//div[@class='parent']/div[@class='copy']/p/text()"
    arr = izip(tree.findall(title_filter), tree.findall(copy_filter))
    

    您可能需要从 xpath 中删除 text() 调用并将其移动到生成器表达式中,我不确定 findall 是否会尊重它。如果没有,类似:

    arr = izip(title.text for title in tree.findall(title_filter), copy.text for copy in tree.findall(copy_filter))
    

    如果父 div 中可能有多个标题/副本对,您可能需要调整该 xpath。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 2011-01-06
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      相关资源
      最近更新 更多