LoginSignup
4
5

More than 5 years have passed since last update.

Ruby + Mechanize で Yahoo! JAPAN の花粉飛散予報を取得する(2018年版)

Last updated at Posted at 2018-01-31

概要

Web サイト 花粉対策特集 - Yahoo!特別企画 を Ruby + Mechanize でスクレイピングして花粉飛散予報を取得する。

花粉飛散情報について

  • 花粉飛散予報は今日と明日の2日分
  • 沖縄県の花粉情報は無い
  • 飛散量には「少ない」「やや多い」「多い」「非常に多い」「飛散前」「飛散終了」「情報なし」などの文字列が入ると思われる

参考: 名古屋市中区の花粉情報 | 花粉症特集 - Yahoo!特別企画

kafunrank.png

Ruby によるサンプルコード

スクレイピングのためのライブラリとして mechanize を利用する。

require 'mechanize'

# 花粉飛散情報。
#
# データソース:
# 花粉対策特集 - Yahoo!特別企画 {https://kafun.yahoo.co.jp/}
class Kafun

  # 花粉飛散情報を取得する。
  #
  # @param pref_id [String]     JIS X 0401 都道府県コード
  # @param detail  [true/false] 詳細情報(2日分の花粉予報)を取得するか?
  # @return [Hash]
  def get(pref_id, detail=false)

    # URLの例
    # 北海道: https://kafun.yahoo.co.jp/weather/1/ ← 「01」じゃなくて「1」
    # 愛知県: https://kafun.yahoo.co.jp/weather/23/
    # 沖縄県のデータは無し
    # 都道府県コードが「01」で来ても「1」になるように to_i
    url = "https://kafun.yahoo.co.jp/weather/#{pref_id.to_i}/"

    agent = Mechanize.new
    page  = agent.get(url)

    date = page.search('.date').inner_text
    area = page.search('.dataBox__areaName a')
    data = page.search('.dataBox__pollenData .text')
    kind = page.search('.dataBox__pollenKind .text')

    area_list = []
    area.each_with_index do |e, i|
      area_list << { # 地域毎にデータを持つ構造に
        :area => e.inner_text, # 地域名
        :url  => "https:#{e[:href]}", # URL
        :data => [{ # 花粉飛散情報(日付別データの配列)
          :date => date, # 日付
          :rank => data[i].inner_text, # 飛散量
          :kind => kind[i].inner_text # 種類
        }]
      }
    end

    if detail
      detail_area_list = []
      area_list.each do |e|
        # 2日分の花粉飛散情報を取得
        detail_area_list << get_detail(e[:url], e[:area])
      end
      detail_area_list
    else
      # 1日分の花粉飛散情報を返す
      area_list
    end
  end

  private

  def get_detail(url, area)

    agent = Mechanize.new
    page  = agent.get(url)

    date = page.search('.dataBox__date')
    data = page.search('.dataBox__pollenData .text')
    kind = page.search('.dataBox__pollenData .text__kind')

    list = [] # 花粉飛散情報(日付別データの配列)
    date.each_with_index do |e, i|
      list << {
        :date => e.inner_text, # 日付
        :rank => data[i].inner_text, # 飛散量
        :kind => kind[i].inner_text # 種類
      }
    end

    {
      :area => area, # 地域名
      :url  => url, # URL
      :data => list # 花粉飛散情報(日付別データの配列)
    }
  end
end

puts '愛知県(都道府県コードは23)の花粉飛散情報を取得する(1日分)'
pp Kafun.new.get('23')
puts

puts '愛知県(都道府県コードは23)の花粉飛散情報を取得する(2日分)'
pp Kafun.new.get('23', true)
puts

サンプルコードの実行結果

愛知県(都道府県コードは23)の花粉飛散情報を取得する(1日分)
[{:area=>"名古屋市中区",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23106/",
  :data=>[{:date=>"1月31日", :rank=>"飛散前", :kind=>"スギ花粉中心"}]},
 {:area=>"豊橋市",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23201/",
  :data=>[{:date=>"1月31日", :rank=>"飛散前", :kind=>"スギ花粉中心"}]},
 {:area=>"岡崎市",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23202/",
  :data=>[{:date=>"1月31日", :rank=>"飛散前", :kind=>"スギ花粉中心"}]},
 {:area=>"設楽町",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23561/",
  :data=>[{:date=>"1月31日", :rank=>"飛散前", :kind=>"スギ花粉中心"}]}]

愛知県(都道府県コードは23)の花粉飛散情報を取得する(2日分)
[{:area=>"名古屋市中区",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23106/",
  :data=>
   [{:date=>"1/31(水)", :rank=>"飛散前", :kind=>"スギ花粉中心"},
    {:date=>"2/1(木)", :rank=>"少ない", :kind=>"スギ花粉中心"}]},
 {:area=>"豊橋市",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23201/",
  :data=>
   [{:date=>"1/31(水)", :rank=>"飛散前", :kind=>"スギ花粉中心"},
    {:date=>"2/1(木)", :rank=>"少ない", :kind=>"スギ花粉中心"}]},
 {:area=>"岡崎市",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23202/",
  :data=>
   [{:date=>"1/31(水)", :rank=>"飛散前", :kind=>"スギ花粉中心"},
    {:date=>"2/1(木)", :rank=>"少ない", :kind=>"スギ花粉中心"}]},
 {:area=>"設楽町",
  :url=>"https://kafun.yahoo.co.jp/weather/23/23561/",
  :data=>
   [{:date=>"1/31(水)", :rank=>"飛散前", :kind=>"スギ花粉中心"},
    {:date=>"2/1(木)", :rank=>"少ない", :kind=>"スギ花粉中心"}]}]

参考資料

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5