nokogiriをつかってリンクを取得

#やりたいこと
<a href="http://shopping.yahoo.co.jp/category/2510/2327/45931/45933/stores/" target="_blank">エレキギター本体 ストア一覧</a>から店舗リンクを取得したい。

##実行準備
初期セットアップは参考にしたリンクを参照。

```test.rake
require 'open-uri'
require 'nokogiri'

namespace :scrape do
  desc"店舗一覧ページから店舗リンクを取得テスト"
  task :scrape_shop_links => :environment do
    url = "http://shopping.yahoo.co.jp/category/2510/2327/45931/45933/stores/"
    charset = nil
    html = open(url) do |f|
      charset = f.charset
      f.read
    end

    doc = Nokogiri::HTML.parse(html, nil, charset)
    shops = doc.css(".elMain")
    #shop_list = shops.css("li")
    count = 0
    data = []
    shops.each do |shop|
      count += 1
      url = shop.css("a")[0][:href]
      name = shop.css("span.elStoreName")[0]
      puts url, name
    end
  end
end
```

アウトプットが

```
javascript:void(0);

http://store.shopping.yahoo.co.jp/aoupprcgigiwgd7i6y2ztfylwi/
<span class="elStoreName">AステージYahoo!店</span>
http://store.shopping.yahoo.co.jp/apollon/
<span class="elStoreName">あぽろんYahoo!店</span>
http://store.shopping.yahoo.co.jp/lostboys-guitars/
<span class="elStoreName">Unlimited Guitars</span>
http://store.shopping.yahoo.co.jp/unliminet/
<span class="elStoreName">UNLIMINET</span>
http://store.shopping.yahoo.co.jp/e-yoshiyagakki/
<span class="elStoreName">e-よしや楽器</span>
http://store.shopping.yahoo.co.jp/ikebe/
<span class="elStoreName">イケベ楽器店</span>
http://store.shopping.yahoo.co.jp/ikebe-revole/
<span class="elStoreName">イケベ楽器リボレ秋葉原店</span>
http://store.shopping.yahoo.co.jp/ishibashi/
<span class="elStoreName">イシバシ楽器</span>
http://store.shopping.yahoo.co.jp/ishibashi-shops/
<span class="elStoreName">イシバシ楽器 17ショップス</span>
http://store.shopping.yahoo.co.jp/illusion/
<span class="elStoreName">一期一会本舗 ギター初心者も安心</span>
http://store.shopping.yahoo.co.jp/itogakki/
<span class="elStoreName">伊藤楽器</span>
http://store.shopping.yahoo.co.jp/wizard-leather/
<span class="elStoreName">WIZARD LEATHER</span>
http://store.shopping.yahoo.co.jp/wavehouse/
<span class="elStoreName">WaveHouse</span>
http://store.shopping.yahoo.co.jp/alien-soundworks/
<span class="elStoreName">Alien Soundworks</span>
http://store.shopping.yahoo.co.jp/sgtech/
<span class="elStoreName">エスジーテクノロジーズ</span>
http://store.shopping.yahoo.co.jp/music-kingdom/
<span class="elStoreName">エレキギター 初心者セット音楽堂</span>
http://store.shopping.yahoo.co.jp/ebisound/
<span class="elStoreName">エレキギターとウクレレのEbiSound</span>
http://store.shopping.yahoo.co.jp/sound-station/
<span class="elStoreName">エレキギターのSOUND STATION</span>
http://store.shopping.yahoo.co.jp/audio-mania/
<span class="elStoreName">Audio Mania</span>
http://store.shopping.yahoo.co.jp/owariya-gakki/
<span class="elStoreName">おかげ様で創業104年オワリヤ楽器</span>
http://store.shopping.yahoo.co.jp/funhoused/
<span class="elStoreName">音楽屋ファンハウス</span>
http://store.shopping.yahoo.co.jp/sendaiguitar/
<span class="elStoreName">音色研究会</span>
http://store.shopping.yahoo.co.jp/on-you-music/
<span class="elStoreName">オンユー楽器・ヤフー店</span>
http://store.shopping.yahoo.co.jp/gakki-de-genki/
<span class="elStoreName">楽器de元気</span>
http://store.shopping.yahoo.co.jp/crossroad-oyama/
<span class="elStoreName">楽器店 CROSSROAD</span>
http://store.shopping.yahoo.co.jp/gakki/
<span class="elStoreName">楽器天国</span>
http://store.shopping.yahoo.co.jp/manmandougakki/
<span class="elStoreName">楽器店まんまん堂</span>
http://store.shopping.yahoo.co.jp/rotomusic/
<span class="elStoreName">楽器の買取販売 ロトミュージック</span>
http://store.shopping.yahoo.co.jp/okumuragakki/
<span class="elStoreName">楽器の総合デパート オクムラ楽器</span>
http://store.shopping.yahoo.co.jp/gakki-mori/
<span class="elStoreName">楽器の森</span>
http://store.shopping.yahoo.co.jp/g-monogatari/
<span class="elStoreName">楽器モノガタリ</span>
http://store.shopping.yahoo.co.jp/g-sakai/
<span class="elStoreName">楽器屋のSAKAI</span>
http://store.shopping.yahoo.co.jp/gakkiland-thanks/
<span class="elStoreName">楽器ランド サンクス</span>
http://store.shopping.yahoo.co.jp/musicgear/
<span class="elStoreName">KANAZAWA TK</span>
http://store.shopping.yahoo.co.jp/suwano/
<span class="elStoreName">株式会社 木下楽器店</span>
http://store.shopping.yahoo.co.jp/jd52k3mnwfd5sap7qlk4eugtee/
<span class="elStoreName">Guitarshopabc</span>
http://store.shopping.yahoo.co.jp/guitarplanet/
<span class="elStoreName">ギタープラネット Yahoo!ショップ</span>
http://store.shopping.yahoo.co.jp/gwnn/
<span class="elStoreName">Guitar Proshop GWNN ネットストア</span>
http://store.shopping.yahoo.co.jp/kurosawa-unplugged/
<span class="elStoreName">GUITAR MUSEUM</span>
http://store.shopping.yahoo.co.jp/cfhnjs2sr46pd23uzihqf7vtkq/
<span class="elStoreName">Good Guitars</span>
http://store.shopping.yahoo.co.jp/groovemusic/
<span class="elStoreName">グルーヴミュージックストア</span>
http://store.shopping.yahoo.co.jp/grace-music-store/
<span class="elStoreName">Graceミュージックストア ヤフー店</span>
http://store.shopping.yahoo.co.jp/kurosawashibuya/
<span class="elStoreName">クロサワ楽器店G-CLUB渋谷</span>
http://store.shopping.yahoo.co.jp/honten/
<span class="elStoreName">クロサワ楽器 日本総本店 WEBSHOP</span>
http://store.shopping.yahoo.co.jp/ksound-yh/
<span class="elStoreName">Ksound Yahoo!ショッピング SHOP</span>
http://store.shopping.yahoo.co.jp/genzovintageguitars/
<span class="elStoreName">GENZO VINTAGE GUITARS</span>
http://store.shopping.yahoo.co.jp/koeido1/
<span class="elStoreName">光栄堂楽器Yahoo!店</span>
http://store.shopping.yahoo.co.jp/koyogakki/
<span class="elStoreName">光洋楽器</span>
http://store.shopping.yahoo.co.jp/cocosoundweb/
<span class="elStoreName">COCOSOUND Yahoo!ショップ</span>
http://store.shopping.yahoo.co.jp/cosmogakki/
<span class="elStoreName">コスモ楽器</span>
```

`javascript:void(0);`をどうにかするのと、spanタグからテキストだけを摘出しなければ。。。

###出力データの整形

<a href="https://github.com/ZIGExN/ruby-training/wiki/Web%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E6%A4%9C%E7%B4%A2%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%A9%E6%A7%8B%E7%AF%89%E5%85%A5%E9%96%80#user-content-htmlの解析" target="_blank">Webスクレイピングを用いたデータ検索クローラ構築入門</a>を参考にしながら

```test.rake
require 'open-uri'
require 'nokogiri'

namespace :scrape do
  desc"店舗一覧ページから店舗リンクを取得テスト"
  task :scrape_shop_links => :environment do
    url = "http://shopping.yahoo.co.jp/category/2510/2327/45931/45933/stores/"
    charset = nil
    html = open(url) do |f|
      charset = f.charset
      f.read
    end

    doc = Nokogiri::HTML.parse(html, nil, charset)
    shops = doc.css(".elMain")
    #shop_list = shops.css("li")
    count = 0
    data = []
    shops.each do |shop|
      count += 1
      url = shop.css("a")[0][:href]
      name = shop.css("span.elStoreName").text
      puts "name: #{name}, url: #{url}"
    end
  end
end
```

```

```

`name = shop.css("span.elStoreName")[0].text`
と入力すると`NoMethodError: undefined method 'text' for nil:NilClass`と言われ怒られてしまう。なぜだろうか。。

上にも記述したが、`name = shop.css("span.elStoreName")[0]`は`span.elStoreName`タグのついた最初の要素を取ってくる。

```
<span class="elStoreName">愛曲楽器 桜山本店</span>
<span class="elStoreName">AステージYahoo!店</span>
<span class="elStoreName">あぽろんYahoo!店</span>
<span class="elStoreName">Unlimited Guitars</span>
<span class="elStoreName">UNLIMINET</span>
<span class="elStoreName">e-よしや楽器</span>
<span class="elStoreName">イケベ楽器店</span>
<span class="elStoreName">イケベ楽器リボレ秋葉原店</span>
<span class="elStoreName">イシバシ楽器</span>
<span class="elStoreName">イシバシ楽器 17ショップス</span>
<span class="elStoreName">一期一会本舗 ギター初心者も安心</span>
<span class="elStoreName">伊藤楽器</span>
<span class="elStoreName">WIZARD LEATHER</span>
<span class="elStoreName">WaveHouse</span>
<span class="elStoreName">Alien Soundworks</span>
<span class="elStoreName">エスジーテクノロジーズ</span>
<span class="elStoreName">MHJ Yahoo!店</span>
<span class="elStoreName">MGM楽器店</span>
<span class="elStoreName">エレキギター 初心者セット音楽堂</span>
<span class="elStoreName">Audio Mania</span>
<span class="elStoreName">オーディオ渡辺 ショッピング</span>
<span class="elStoreName">おかげ様で創業104年オワリヤ楽器</span>
<span class="elStoreName">音楽屋ファンハウス</span>
<span class="elStoreName">音色研究会</span>
<span class="elStoreName">オンユー楽器・ヤフー店</span>
<span class="elStoreName">楽器de元気</span>
<span class="elStoreName">楽器店 CROSSROAD</span>
<span class="elStoreName">楽器天国</span>
<span class="elStoreName">楽器店まんまん堂</span>
<span class="elStoreName">楽器の買取販売 ロトミュージック</span>
<span class="elStoreName">楽器の総合デパート オクムラ楽器</span>
<span class="elStoreName">楽器の森</span>
<span class="elStoreName">楽器モノガタリ</span>
<span class="elStoreName">楽器屋のSAKAI</span>
<span class="elStoreName">楽器ランド サンクス</span>
<span class="elStoreName">KANAZAWA TK</span>
<span class="elStoreName">株式会社 木下楽器店</span>
<span class="elStoreName">Guitarshopabc</span>
<span class="elStoreName">ギタープラネット Yahoo!ショップ</span>
<span class="elStoreName">Guitar Proshop GWNN ネットストア</span>
<span class="elStoreName">GUITAR MUSEUM</span>
<span class="elStoreName">Good Guitars</span>
<span class="elStoreName">グルーヴミュージックストア</span>
<span class="elStoreName">Graceミュージックストア ヤフー店</span>
<span class="elStoreName">クロサワ楽器店G-CLUB渋谷</span>
<span class="elStoreName">クロサワ楽器 日本総本店 WEBSHOP</span>
<span class="elStoreName">Ksound Yahoo!ショッピング SHOP</span>
<span class="elStoreName">GENZO VINTAGE GUITARS</span>
<span class="elStoreName">光栄堂楽器Yahoo!店</span>
<span class="elStoreName">光洋楽器</span>
```

一方で`shop.css("span.elStoreName")`が出すアウトプットもまるで変わりがない。

```
<span class="elStoreName">愛曲楽器 桜山本店</span>
<span class="elStoreName">AステージYahoo!店</span>
<span class="elStoreName">あぽろんYahoo!店</span>
<span class="elStoreName">Unlimited Guitars</span>
<span class="elStoreName">UNLIMINET</span>
<span class="elStoreName">e-よしや楽器</span>
<span class="elStoreName">イケベ楽器店</span>
<span class="elStoreName">イケベ楽器リボレ秋葉原店</span>
<span class="elStoreName">イシバシ楽器</span>
<span class="elStoreName">イシバシ楽器 17ショップス</span>
<span class="elStoreName">一期一会本舗 ギター初心者も安心</span>
<span class="elStoreName">伊藤楽器</span>
<span class="elStoreName">WIZARD LEATHER</span>
<span class="elStoreName">WaveHouse</span>
<span class="elStoreName">Alien Soundworks</span>
<span class="elStoreName">エスジーテクノロジーズ</span>
<span class="elStoreName">MHJ Yahoo!店</span>
<span class="elStoreName">MGM楽器店</span>
<span class="elStoreName">エレキギター 初心者セット音楽堂</span>
<span class="elStoreName">Audio Mania</span>
<span class="elStoreName">オーディオ渡辺 ショッピング</span>
<span class="elStoreName">おかげ様で創業104年オワリヤ楽器</span>
<span class="elStoreName">音楽屋ファンハウス</span>
<span class="elStoreName">音色研究会</span>
<span class="elStoreName">オンユー楽器・ヤフー店</span>
<span class="elStoreName">楽器de元気</span>
<span class="elStoreName">楽器店 CROSSROAD</span>
<span class="elStoreName">楽器天国</span>
<span class="elStoreName">楽器店まんまん堂</span>
<span class="elStoreName">楽器の買取販売 ロトミュージック</span>
<span class="elStoreName">楽器の総合デパート オクムラ楽器</span>
<span class="elStoreName">楽器の森</span>
<span class="elStoreName">楽器モノガタリ</span>
<span class="elStoreName">楽器屋のSAKAI</span>
<span class="elStoreName">楽器ランド サンクス</span>
<span class="elStoreName">KANAZAWA TK</span>
<span class="elStoreName">株式会社 木下楽器店</span>
<span class="elStoreName">Guitarshopabc</span>
<span class="elStoreName">ギタープラネット Yahoo!ショップ</span>
<span class="elStoreName">Guitar Proshop GWNN ネットストア</span>
<span class="elStoreName">GUITAR MUSEUM</span>
<span class="elStoreName">Good Guitars</span>
<span class="elStoreName">グルーヴミュージックストア</span>
<span class="elStoreName">Graceミュージックストア ヤフー店</span>
<span class="elStoreName">クロサワ楽器店G-CLUB渋谷</span>
<span class="elStoreName">クロサワ楽器 日本総本店 WEBSHOP</span>
<span class="elStoreName">Ksound Yahoo!ショッピング SHOP</span>
<span class="elStoreName">GENZO VINTAGE GUITARS</span>
<span class="elStoreName">光栄堂楽器Yahoo!店</span>
<span class="elStoreName">光洋楽器</span>
```

ということは`name = shop.css("span.elStoreName")[0].text`は今回のケースにおいては形式上とってこれないのではと推測するのが安全そう。

###`javascript:void(0);`を取り除く

<a href="http://qiita.com/Trickey/items/28f2aaddfe32a0035628#web-スクレイピングで役立つ-xpath-の関数" target="_blank">XPath の関数を使った Web スクレイピング</a>に記載されているような方法も試したのですがいまいちうまくいかなかったので将来的な利便性は低いですがべた書きで取り除いていくことにしました。

```test.rake
require 'open-uri'
require 'nokogiri'

namespace :scrape do
  desc"店舗一覧ページから店舗リンクを取得テスト"
  task :scrape_shop_links => :environment do
    url = "http://shopping.yahoo.co.jp/category/2510/2327/45931/45933/stores/"
    charset = nil
    html = open(url) do |f|
      charset = f.charset
      f.read
    end

    doc = Nokogiri::HTML.parse(html, nil, charset)
    shops = doc.css(".elMain")
    shops_main = shops.search('//a[starts-with(@href, "http://")]')
    count = 0
    data = []
    shops.each do |shop|
      url = shop.css("a")[0][:href]
      next if url == "javascript:void(0);"
      count += 1
      name = shop.css("span.elStoreName").text
      puts "#{count}, name: #{name}, url: #{url}"
    end
  end
end
```

##追記

okkez@github様よりもっと短く作れるとのアドバイスをいただきました。量的には半分以下になります。ご教授頂きありがとうございました。

```test.rake
require "open-uri"
require "nokogiri"

desc "scrapint testだよおおおおお"
task :test_scrape => :environment do  
  html = open("http://shopping.yahoo.co.jp/category/2510/2327/45931/45933/stores/")
  doc = Nokogiri::HTML(html)
  doc.search(".mdStoreList div.elItem > ul > li").each do |element|
    p [element.at("a.elStore")["href"], element.at("span.elStoreName").inner_text]
  end
end
```

#参考にしたリンク
- <a href="http://morizyun.github.io/blog/nokogiri-scraping-ruby-rails-begineer/" target="_blank">【Rails初学者向け】Nokogiriをつかって他のWebサイトから情報を取得しよう</a>
- <a href="http://shgam.hatenadiary.jp/entry/2013/11/09/192509" target="_blank">nokogiriを使ったスクレイピング入門</a>
- <a href="http://hetaredream.hatenablog.com/entry/2014/12/20/163310" target="_blank">Nokogiriを使ったRubyでのスクレイピング　〜初心者編〜</a>
- <a href="http://qiita.com/weedslayer/items/23600391a2645264732c" target="_blank">Ruby: スクレイピングしたデータをHerokuへアップロード出来ない</a>
- <a href="http://d.hatena.ne.jp/otn/20090509/p1" target="_blank">RubyスクレイピングのためのNokogiri利用メモ</a>