0

html ファイルが与えられた場合:

<div>
    <div class="NormalMid">
        <span class="style-span">
            "Data 1:"
            <a href="http://site.com/data/1">1</a>
            <a href="http://site.com/data/2">2</a>
        </span>
    </div>
   ...more divs
    <div class="NormalMid">
        <span class="style-span">
            "Data 20:"  
            <a href="http://site.com/data/20">20</a>
            <a href="http://site.com/data/21">21</a>
            <a href="http://site.com/data/22">22</a>
            <a href="http://site.com/data/23">23</a>
        </span>
    </div>
    ...more divs
</div

これらの SO 投稿を参照として使用: Ruby でマイニングするこれら 2 つの条件ブロック コードを統合するにはどうすればよいですか? Rubyでこの配列と ループを理解する方法は?

私のコード:

require 'nokogiri'
require 'pp'
require 'open-uri'

data_file = 'site.htm'
file = File.open(data_file, 'r')
html = open(file)
page = Nokogiri::HTML(html)
page.encoding = 'utf-8'

rows = page.xpath('//div[@class="NormalMid"]')
details = rows.collect do |row|
    detail = {}
    [
        [row.children.first.element_children,row.children.first.element_children],
    ].each do |part, link|
        data = row.children[0].children[0].to_s.strip
        links = link.collect {|item| item.at_xpath('@href').to_s.strip}
        detail[data.to_sym] = links
    end
    detail
end
details.reject! {|d| d.empty?}
pp details

出力:

[{:"Data 1:"=>
   ["http://www.site.com/data/1",
    "http://www.site.com/data/2"]},
 ...
 {:"Data 20 :"=>
   ["http://www.site.com/data/20",
    "http://www.site.com/data/21",
    "http://www.site.com/data/22",
    "http://www.site.com/data/20",]},
 ... 
}]

まさに私が望んでいたことです。

しかし、これらのコード行を変更すると:

 detail = {}
    [
       [row.children.first.element_children,row.children.first.element_children],
    ].each do |part, link| 

に:

 detail = {}
    [
       [row.children.first.element_children],
    ].each do |link| 

私はの出力を得る

[{:"Data 1:"=>
   ["http://www.site.com/data/1"]},
 ...
 {:"Data 20 :"=>
   ["http://www.site.com/data/20"]},
 ... 
}]

最初のアンカー href のみが配列に格納されます。

引数リストの引数が使用されていないため、なぜそのように動作するのかを明確にするpart必要があります。私はそこにそれを必要としなかったと考えています。しかし、対応するものも削除すると、私のプログラムは正しく動作しませんrow.children.first.element_children

[[obj,obj],].each doブロックで何が起こっているのですか?1 週間前に Ruby を始めたばかりで、まだ構文に慣れているところです。ありがとう:D

EDIT rows[0].children.first.element_children[0]には出力があります

Nokogiri::XML::Element:0xcea69c name="a" attributes=[#<Nokogiri::XML::Attr:0xcea648
name="href" value="http://www.site.com/data/1">] children[<Nokogiri::XML::Text:0xcea1a4
"1">]>

puts rows[0].children.first.element_children[0]

 <a href="http://www.site.com/data/1">1</a>
4

1 に答える 1

1

コードを過度に複雑にしました。あなたのコードを見ると、以下のようなものを取得しようとしているようです:

require 'nokogiri'

doc = Nokogiri::HTML::Document.parse <<-eotl
<div>
    <div class="NormalMid">
        <span class="style-span">
            "Data 1:"
            <a href="http://site.com/data/1">1</a>
            <a href="http://site.com/data/2">2</a>
        </span>
    </div>
    <div class="NormalMid">
        <span class="style-span">
            "Data 20:"  
            <a href="http://site.com/data/20">20</a>
            <a href="http://site.com/data/21">21</a>
            <a href="http://site.com/data/22">22</a>
            <a href="http://site.com/data/23">23</a>
        </span>
    </div>
</div
eotl

rows = doc.xpath("//div[@class='NormalMid']/span[@class='style-span']")
val = rows.map do |row|
    [row.at_xpath("./text()").to_s.tr('"','').strip,row.xpath(".//@href").map(&:to_s)]
end

Hash[val]
# => {"Data 1:"=>["http://site.com/data/1", "http://site.com/data/2"],
#     "Data 20:"=>
#      ["http://site.com/data/20",
#       "http://site.com/data/21",
#       "http://site.com/data/22",
#       "http://site.com/data/23"]}

[[obj,obj],].each do ブロックで何が起こっているのでしょうか?

以下の 2 つの部分を見てください。

[[1],[4,5]].each do |a|
  p a
end
# >> [1]
# >> [4, 5]

[[1,2],[4,5]].each do |a,b|
    p a, b
end
# >> 1
# >> 2
# >> 4
# >> 5
于 2013-09-14T12:14:55.323 に答える