こんにちは。ルーターにてアルバイトをしております、Tsuboiです。

今回はRubyにおけるCSV(Comma-Separated Values)ファイルとJSON(JavaScript Object Notation)ファイルの入出力についての基本的な説明です。

JSONはWebスクレイピングをする際に非常によく見かける形式ですし、CSVはスクレイピング/クローリングしたデータの出力形式としてポピュラーですので、これらのファイル形式の取り回しはスクレイピングエンジニアとしては必須ですね。ということで、Rubyにはcsvライブラリ、jsonライブラリという便利なライブラリが実装されているので、これらを使ってファイルを扱う方法を紹介したいと思います。

csvライブラリによる入出力

簡単な例として下のようなfoo.csvを用いて初台駅、新宿駅、代々木駅の緯度と経度のデータを扱う場面を考えましょう。1列目が駅名、2列目が緯度、3列目が経度です。

"初台駅",35.680986,139.686182
"新宿駅",35.690553,139.699579
"代々木駅",35.684043,139.702188

最初にライブラリを読み込みます。

require "csv"

Ruby公式リファレンスでは5つのメソッドが紹介されています。それぞれの使い方を見てみましょう。

まずは読み込みからです。

openメソッド

ファイルをCSVクラスとして読み込みます。このCSVクラスは下のようにeachメソッドを用いることで、1行ごとをArrayクラスとして扱うことができます。

CSV.open("foo.csv") do |csv|
    puts csv.class
    csv.each do |row|
        p row
        puts row.class
    end
end
#出力結果
#CSV
#["初台駅", "35.680986", "139.686182"]
#Array
#["新宿駅", "35.690553", "139.699579"]
#Array
#["代々木駅", "35.684043", "139.702188"]
#Array

foreachメソッド

上のように1行ずつ操作を行う場合はforeachメソッドを用いるのが便利です。行をArrayクラスとして扱います。

CSV.foreach("foo.csv") do |row|
    p row
    puts row.class
end
#出力結果
#["初台駅", "35.680986", "139.686182"]
#Array
#["新宿駅", "35.690553", "139.699579"]
#Array
#["代々木駅", "35.684043", "139.702188"]
#Array

readメソッド

ファイル全体を一気にArrayクラスとして読み込みたいときはreadメソッドを用います。

foo_csv = CSV.read("foo.csv")
p foo_csv
puts foo_csv.class
#出力結果
#[["初台駅", "35.680986", "139.686182"], ["新宿駅", "35.690553", "139.699579"], ["代々木駅", "35.684043", "139.702188"]]
#Array

parseメソッド

ファイルからではなく、文字列から読み込む際はparseメソッドを用います。

foo_csv = CSV.parse("初台駅",35.680986,139.686182\n"新宿駅",35.690553,139.699579\n"代々木駅",35.684043,139.702188)
p foo_csv
puts foo_csv.class
#出力結果
#[["初台駅", "35.680986", "139.686182"], ["新宿駅", "35.690553", "139.699579"], ["代々木駅", "35.684043", "139.702188"]]
#Array

これで、各駅の緯度と経度のデータがRuby上で扱えるようになりました。次に出力をするためのメソッドを見ていきましょう。

openメソッド

入力の時に用いたopenメソッドにw(write)オプションをつけるとファイルへの書き込みができるようになります。書き込む内容はArrayにして渡します。

CSV.open("bar.csv", "w") do |csv|
    csv << ["初台駅", "35.680986", "139.686182"]
    csv << ["新宿駅", "35.690553", "139.699579"]
    csv << ["代々木駅", "35.684043", "139.702188"]
end

generateメソッド

文字列へ書き込む際はgenerateメソッドを使います。

bar_str = CSV.generate do |csv|
    csv << ["初台駅", "35.680986", "139.686182"]
    csv << ["新宿駅", "35.690553", "139.699579"]
    csv << ["代々木駅", "35.684043", "139.702188"]
end
puts bar_str
#出力結果
#"代々木駅",35.684043,139.702188
#"新宿駅",35.690553,139.699579
#"初台駅",35.680986,139.686182

以上がCSVファイルの扱いについての説明です。

jsonライブラリによる入出力

そもそもJSONとは何でしょうか?JSONウィキペディアでは以下のように説明されています。

JSON(ジェイソン、JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptにおけるオブジェクトの表記法をベースとしているが、JSONはJavaScript専用のデータ形式では決してなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しに使えるよう設計されている。

互換性の良いデータ形式なので、他のプログラミング言語などとデータをやりとりする場面ではJSONを用いることも多いかと思います。

では具体的にJSONの扱いについても見ていきましょう。CSVのときと同様に駅の緯度と経度を扱う場合を考えます。”lat”が緯度、”lon”が経度です。

{"初台駅":{"lat":"35.680986","lon":"139.686182"},"新宿駅":{"lat":"35.690553","lon":"139.699579"},"代々木駅":{"lat":"35.684043","lon":"139.702188"}}

最初にライブラリを読み込みます。

require "json"

loadメソッド

JSONを読み込むにはloadメソッドを使います。JSON形式の文字列を受け取ってArrayやHashオブジェクトにして返すものです。

foo_hash = {}
open("foo.json") do |file|
    foo_hash = JSON.load(file)
end
puts foo_hash
puts foo_hash.class
#出力結果
#{"初台駅"=>{"lat"=>"35.680986", "lon"=>"139.686182"}, "新宿駅"=>{"lat"=>"35.690553", "lon"=>"139.699579"}, "代々木駅"=>{"lat"=>"35.684043", "lon"=>"139.702188"}}
#Hash

次に出力方法です。

dumpメソッド

bar_str = JSON.dump(foo_hash)
puts bar_str
puts bar_str.class
#出力結果
#{"初台駅":{"lat":"35.680986","lon":"139.686182"},"新宿駅":{"lat":"35.690553","lon":"139.699579"},"代々木駅":{"lat":"35.684043","lon":"139.702188"}}
#String
ArrayやHashオブジェクトを受け取ってJSON形式の文字列にして返します。bar.jsonというファイルに書き込む場合は下のようにします。
open("bar.json", "w") do |file|
    JSON.dump(foo_hash, file)
end

これでRuby上でJSONが扱えるようになりました。

おわりに

以上で説明は終わりです。この記事を参考にしてRubyでデータを扱い始める初級者の方が1人でもいらっしゃれば幸いです。