3

次のようなデータがあります。

<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)}
4

2 に答える 2

9

Nokogiriは、主に2つのタイプの検索をサポートしていsearchますatsearchNodeSetを返します。これは、配列のように考える必要があります。atノードを返します。CSSまたはXPath式を使用できます。CSSの方が読みやすいので、私は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  "
]

との唯一の本当の違いは、searchのようなものです。atatsearch(...).first

「スクレイピング時にノードからのすべてのテキストを結合しないようにする方法」も参照してください。

Nokogiriには、便宜上、いくつかの追加のエイリアスがあります:およびat_css、、cssおよび。at_xpathxpath


Pryから切り取った、CSSおよびXPathアクセサーを使用して名前を取得する別の方法を次に示します。

[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"
]
于 2013-03-18T20:32:49.540 に答える
0

xpath式は、期待どおりに<artists><artist>タグではなく、を選択します。これを試してください。

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

"//artists"はすべての「artists」タグを取得します[1]。は、タグ自体の最初の要素ではなく、これらのタグの最初のタグを選択します。

于 2013-03-18T20:22:22.487 に答える