LoginSignup
2
0

More than 1 year has passed since last update.

気象庁の過去気象データを Ruby でスクレイピング

Last updated at Posted at 2022-03-13

このページで Python でやっているのと同じことを、Ruby でやってみたものです。

元ページは簡単な HTML の読み方についても解説されてあります。

やること

気象庁のサイト(例えばこんな感じ)から、

札幌, 室蘭, 函館, 青森, 秋田, 盛岡, 山形, 仙台, 福島, 新潟, 金沢, 富山, 長野, 宇都宮, 福井, 前橋, 熊谷, 水戸, 岐阜, 名古屋, 甲府, 銚子, 津, 静岡, 横浜, 松江, 鳥取, 京都, 彦根, 広島, 岡山, 神戸, 和歌山, 奈良, 松山, 高松, 高知, 徳島, 下関, 福岡, 佐賀, 大分, 長崎, 熊本, 鹿児島, 宮崎

の都市の、

年月日, 陸の平均気圧(hPa), 海の平均気圧(hPa), 降水量(mm), 平均気温(℃), 平均湿度(%), 平均風速(m/s), 日照時間(h)

を取得し、csv形式でファイルに書き出します。

前提

「Nokogiri」という Gem が必要です。gem install nokogiriなどでインストールして下さい。
Linux Mint 20.3 で実行したので、Windows では文字化けが起きるかも知れません。(追記:よく考えてみたら今回のはほぼ数値データしか扱っていないので、文字化けはたぶんないですね。)

コード

Ruby
require "nokogiri"
require "open-uri"
require "csv"

place_codeA = [14, 21, 23, 31, 32, 33, 35, 34, 36, 54, 56, 55, 48, 41, 57, 42, 43, 40, 52, 51, 49, 45, 53, 50, 46, 68, 69, 61, 60, 67, 66, 63, 65, 64, 73, 72, 74, 71, 81, 82, 85, 83, 84, 86, 88, 87]
place_codeB = [47412, 47423, 47430, 47575, 47582, 47584, 47588, 47590, 47595, 47604, 47605, 47607, 47610, 47615, 47616, 47624, 47626, 47629, 47632, 47636, 47638, 47648, 47651, 47656, 47670, 47741, 47746, 47759, 47761, 47765, 47768, 47770, 47777, 47780, 47887, 47891, 47893, 47895, 47762, 47807, 47813, 47815, 47817, 47819, 47827, 47830]
place_name = ["札幌", "室蘭", "函館", "青森", "秋田", "盛岡", "山形", "仙台", "福島", "新潟", "金沢", "富山", "長野", "宇都宮", "福井", "前橋", "熊谷", "水戸", "岐阜", "名古屋", "甲府", "銚子", "津", "静岡", "横浜", "松江", "鳥取", "京都", "彦根", "広島", "岡山", "神戸", "和歌山", "奈良", "松山", "高松", "高知", "徳島", "下関", "福岡", "佐賀", "大分", "長崎", "熊本", "鹿児島", "宮崎"]

base_url = "http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php"

place_data = place_name.zip(place_codeA, place_codeB)
place_data.each do |place, pc_a, pc_b|
  all_list = [['年月日', '陸の平均気圧(hPa)', '海の平均気圧(hPa)', '降水量(mm)', '平均気温(℃)', '平均湿度(%)', '平均風速(m/s)', '日照時間(h)']]
  puts place
  
  (2007..2017).each do |year|
    puts year
    (1..12).each do |month|
      url = base_url + "?prec_no=#{pc_a}&block_no=#{pc_b}&year=#{year}&month=#{month}&day=1&view=p1"
      
      body = Nokogiri::HTML(URI.open(url))    #サイトのHTMLを取得し、Nokogiriに流し込む
      sleep(1)    #サイト攻撃にならないためのマナー
      
      #Nokogiriから返ってきたオブジェクトを加工する
      body.css("tr.mtx").drop(4).each do |row|
        data = row.css("td").map(&:text)    #map(&:text)でtd要素の「中身」を得ている
        
        row_data = ["#{year}/#{month}/#{data[0]}"]
        col_idxs = [1, 2, 3, 6, 9, 11, 16]    #取得する列の一覧
        row_data += col_idxs.map { |i| data[i].to_f.to_s }
        
        all_list << row_data
      end
    end
  end
  
  #ファイルに書き出し
  CSV.open(place + ".csv", "w") do |csv|
    all_list.each { |row| csv << row }
  end
end

元の Python コードにないのはsleep(1)です。直接サイトにアクセスするので、マナーとして入れておきました。また、データをわざわざ一旦 Float に変換するのは、必要ない気もしますがそのままにしてあります。(追記。"--".to_f0.0になることに気づいたので、コードを修正しました。)

なお、sleep(1)を入れてあるせいで、このコードをすべて実行するのにはかなりの時間がかかります。のんびりお待ち下さい。

2
0
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
2
0