gpt4 book ai didi

ruby - 如何在Nokogiri中收集节点的几个元素中的第一个

转载 作者:太空宇宙 更新时间:2023-11-03 17:16:51 24 4
gpt4 key购买 nike

我的数据如下所示:

<release> 
<artists>
<artist>
<name>Johnny Mnemonic</name>
</artist>
<artist>
<name>Constantine</name>
</artist>
<artists>
</release>
<release>
<artists>
<artist>
<name>Speed</name>
</artist>
<artist>
<name>The Matrix</name>
</artist>
<artists>
</release>
...and so on.

对于每个版本,我只需要来自第一个 <artist> 的数据标签。我尝试了以下代码,但它从艺术家那里提取了所有文本:

page = Nokogiri::XML(open("37.xml"))

page.xpath("//artists[1]").each do |el|

File.open("#{LOCAL_DIR}/37.txt", 'a'){|f| f.write(el)}

最佳答案

Nokogiri 支持两种主要类型的搜索,searchatsearch 返回一个 NodeSet,您应该将其视为一个数组。 at 返回一个节点。两者都可以采用 CSS 或 XPath 表达式。我更喜欢 CSS,因为它们更具可读性,但有时您无法轻松地使用一个 CSS 到达想要的位置,因此请尝试另一个。

对于您的问题,使用 text 指定要从中提取文本的节点很重要。如果您的结果太宽泛,除了您想要的标签内的文本之外,您还会从标签之间获得文本。为避免向下钻取到您要阅读的内容的最直接节点:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<release>
<artists>
<artist>
<name>Johnny Mnemonic</name>
</artist>
<artist>
<name>Constantine</name>
</artist>
<artists>
<release>
EOT

因为这些专门查找 name 节点,所以很容易获得所需的文本而不会产生垃圾:

doc.at('name').text                # => "Johnny Mnemonic"
doc.at('artist name').text # => "Johnny Mnemonic"
doc.at('artists artist name').text # => "Johnny Mnemonic"

这些是松散的搜索,因此会返回更多垃圾:

doc.at('artist').text  # => "\n   Johnny Mnemonic\n  "
doc.at('artists').text # => "\n \n Johnny Mnemonic\n \n \n Constantine\n \n \n\n"

使用search 返回多个节点:

doc.search('name').map(&:text)

[
[0] "Johnny Mnemonic",
[1] "Constantine"
]

doc.search('artist').map(&:text)

[
[0] "\n Johnny Mnemonic\n ",
[1] "\n Constantine\n "
]

searchat 之间唯一真正的区别是 at 类似于 search(...).first.

另见“How to avoid joining all text from Nodes when scraping”。

为了方便起见,Nokogiri 有一些额外的别名:at_csscss,以及 at_xpathxpath


这里有替代方法,使用 CSS 和 XPath 访问器获取名称,从 Pry 中截取:

[5] (pry) main: 0> # using CSS with Ruby
[6] (pry) main: 0> artists = doc.search('release').map{ |release| release.at('artist').text.strip }
[
[0] "Johnny Mnemonic",
[1] "Speed"
]
[7] (pry) main: 0> # using CSS with less Ruby
[8] (pry) main: 0> artists = doc.search('release artists artist:nth-child(1) name').map{ |n| n.text }
[
[0] "Johnny Mnemonic",
[1] "Speed"
]
[9] (pry) main: 0>
[10] (pry) main: 0> # using XPath
[11] (pry) main: 0> artists = doc.search('release/artists/artist[1]/name').map{ |t| t.content }
[
[0] "Johnny Mnemonic",
[1] "Speed"
]
[12] (pry) main: 0> # using more XPath
[13] (pry) main: 0> artists = doc.search('release/artists/artist[1]/name/text()').map{ |t| t.content }
[
[0] "Johnny Mnemonic",
[1] "Speed"
]

关于ruby - 如何在Nokogiri中收集节点的几个元素中的第一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15485940/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com