Python

CSVファイルとJSONデータ~Pythonを使って仕事で楽しよう~

PythonでCSV・JSONファイルを編集する

本記事で参考にさせていただいたのは、下記書籍になります。
Pythonを使ってあれこれ便利なことができることについて、具体的な例と共にたくさん掲載されていておススメです。
本内容の理解を深めるために、会話形式を取り入れたり自分なりにまとめ方を工夫してみました。
実際の書籍と合わせて理解を深める一助になれば幸いです!

せんぱい
せんぱい
Pythonで仕事を楽にする方法を学ぼう!シリーズ。
今回はCSVファイルとJSONファイルをPythonから操作する方法について学んていくよ!
今回の内容を通して分かることはこんな感じです!
  • よく使われるデータ形式 CSVとJSONがどんなものか分かる
  • PythonでのCSV・JSONファイルの中身を編集する方法
  • Web上にアップされている、JSONファイルをAPIで取得して欲しい情報を手に入れる!
  • CSVはインターネットに関するいろんな決まり事の中で、RFC 4180によって定義されている!
ガゼルさん
ガゼルさん
CSVファイルってやれ、エクスポートだの、インポートだのするのでこれを機会に詳しくなりたいです!
JSONって…あの厚切りの?
せんぱい
せんぱい
もちろんちがうよ!

Pythonを使ってCSVやJSONファイルを編集できるようになろう!

せんぱい「まず、簡単に各ファイルの特徴について触れるよ」

  • CSVとJSONはプレーンテキストファイル
  • IEDEのファイルエディタのようなテキストエディタで閲覧することが可能。
  • Pythonには**csvやjsonモジュールがある!

ガゼルさん「プレーンテキスト?」

せんぱい「平文とかともいうね。難しく言うと、暗号化されていない文字列のこと。
まあ、中身を見るだけならメモ帳などでも見れるテキストファイルのことだね」

ガゼルさん「中身だけなら…!それ以外はダメなんですか?」

せんぱい「まあ、見にくいよ。それに、Windowsのメモ帳などだと、改行コードなど、目には見えないけれど大切なものをうまく編集できなかったりするので気を付けなきゃいけない」

ガゼルさん「星の王子さま…!
もし、編集するならその目に見えないけれど大切なものをきちんと編集できるエディタで編集する必要があるということですね!」

せんぱい「そゆこと!」

CSVファイルって?

CSVは Camma Separated Values(カンマ区切りの値)の略。
CSVファイルはプレーンテキストに記録された簡単なスプレッドシート。

JSONファイルって?

Javascript Object Notation 。
プレーンテキストに書かれたJavaScriptのソースコードを保持する形式

JSONを使用する為にJavascriptの知識は不要だけど、JSON形式は**多くのWebアプリケーションで用いられているので、知っておくと便利だよ

CSVファイルの特徴

  • CSVファイルの各行はスプレッドシートの行を表している。
  • カンマは、セルを区切る役割を果たす
  • CSVファイルはシンプル、だからこそ多くの種類のプログラムで幅広くサポートされている。

せんい「CSVファイルは単純であり、ExcelやGoogleスプレッドシートにあるような機能の多くがないよ!
例えば…」

  • 値の種別がなくすべてが文字列!
  • フォントのサイズや色を指定できない!
  • 複数のワークシートを保持できない!
  • セルの幅と高さを指定できない!
  • セルを結合できない!
  • 画像や図表を埋め込めない!ほんと文字列した扱えない

サンプルデータ!

『退屈なことはPythonにやらせよう』のリポジトリからもダウンロードできるし、自身で下記内容をテキストエディタに入力して、example.csvなど名前をつけて保存しよう!」

4/5/2014 13:34 Apples 73
4/5/2014 3:41 Cherries 85
4/6/2014 12:46 Pears 14
4/8/2014 8:59 Oranges 52
4/10/2014 2:07 Apples 152
4/10/2014 18:10 Bananas 23
4/10/2014 2:40 Strawberries 98

エクセルでみると

|4/5/2015 13:34|Apples|73|
|4/5/2015 3:45|Cherries|73|

こんな風に見える筈!

せんぱい「上記のような値が入力されたファイルを用い、これから実際にCSVの操作を行ってみよう!」

ツトム先輩の通なポイント!

CSVファイルはカンマで区切られている為、各行でsplit()メソッドを呼び出せばよいと思うかもしれない。
しかし、CSVファイル中のカンマは常にセルの区切りとして使用されているとは限らない。
CSVファイルには独自のエスケープ文字がありカンマなどの文字を値の一部として使用することができる。
split()メソッドはこういったエスケープ文字を扱うことができない

このような潜在的な落とし穴がある為、CSVファイルを読み書きするにはcsvモジュールを使用するのがよい!

せんぱい「このような潜在的な落とし穴がある為、CSVファイルを読み書きするにはcsvモジュールを使用するのがよいよ!」

ここからCSVモジュールの登場だ!

CSVファイルからデータを読み込むために必要!Readerオブジェクト風に見える筈!

csvモジュールを使用しCSVファイルからデータを読み込むためにはReaderオブジェクトを生成する。
Readerオブジェクトを用いるとCSVファイルの行を順番に処理することが可能。
サンプルCSV、example.csvをカレントディレクトリに置き、次のようにインタラクティブシェルに入力してみよう!

import csv

example_file = open('example.csv')

example_reader = csv.reader(example_file)

example_data = list(example_reader)

example_data

[[‘4/5/2014 13:34’, ‘Apples’, ’73’], [‘4/5/2014 3:41’, ‘Cherries’, ’85’], [‘4/6/2014 12:46’, ‘Pears’, ’14’], [‘4/8/2014 8:59’, ‘Oranges’, ’52’], [‘4/10/2014 2:07’, ‘Apples’, ‘152’], [‘4/10/2014 18:10’, ‘Bananas’, ’23’], [‘4/10/2014 2:40’, ‘Strawberries’, ’98’]]

せんぱい「ででんと!こんな感じで出力されます!
コメントアウトで補足しつつ、くわしくみていくよ!


#csvモジュールはPython付属の為、別途、インストールせずにインポートすることが可能だよ! #で、早速インポート! import csv #csvモジュールでCSVファイルを読み込むためには通常のテキストファイルと同様にopen()関数でCSVファイルを開く example_file = open('example.csv') #ただ、open()が返したFileオブジェクトのread()やreadlines()メソッドを呼び出すのではなく、csv.reader()関数に渡す。 #csv.reader()にはファイル名を直接渡すわけでもない点に注意 example_reader = csv.reader(example_file) #Readerオブジェクトの値に最も直接的にアクセスする方法はlist()に渡して通常のPythonリストに変換すること。 example_data = list(example_reader) #Readerオブジェクトをlist()に渡すとリストのリストが返ってくるため変数example_dataに保持しておく。 #example_data、と入力するとリストのリストが表示される。 example_data

ガゼルさん「CSVファイルを開いて、データを編集するには読み込んだオブジェクトを一度、csv.reader()で湯煎するような感じになるんですね!」

せんぱい「湯煎という表現が正しいか分からないけれど!
でもまあ、これでCSVファイルをリストのリストに変換できたんだ。
なので、特定の行と列をexample_data[row][col]の式でアクセスすることが可能になったよ!」

ガゼルさん「example_data[row][col]!?」

row→example_dataからリストをひとつ取り出すインデックス

col→そのリストから要素をひとつ取り出すインデックス

せんぱい「って、ことになるよ!
サンプルを見てみよう!」

example_data[0][0]

せんぱい「だと、’4/5/2014 13:34’ が出力されるよ!」

example_data[0][1]

せんぱい「だと、’Apples’ が出力されるよ!」

example_data[0][2]

せんぱい「だと、 ’73’ が出力されるよ!」

example_data[1][1]

せんぱい「だと、’Cherries’ が出力されるよ!」

example_data[6][1]

せんぱい「だと、 ’Strawberries’ が出力されるよ!
これらを見て、分かるとおり
example_data[0][0]は1番目の1番目の文字列を表して、
example_data[0][2]は1番目のリストの3番目の文字列を表すってことだね!」

巨大なファイルはforループを使え!!

せんぱい「巨大なCSVファイルの場合、forループの中でReaderオブジェクトを使用するとよいよ。
そうすることにより、分解して読み込み、ファイル全体を一度にメモリーに読み込むことが避けられる」

ガゼルさん「メモリーに一度に読み込んじゃうとアップアップしちゃうってことですね」

サンプル
import csv
example_file = open('example_csv')
example_reader = csv.reader(exampe_file)
for row in example_reader:
  print('Row #' + str(example_reader.line_num) + '' + str(row))

せんぱい「はい!ファイルの中身が表示されましたと!
で、次はそれぞれ詳しくみてみるよ!」

#はい、まずはcsvモジュールをインポート!
import csv

#CSVファイルからReaderオブジェクトを生成!
example_file = open('example_csv')
example_reader = csv.reader(exampe_file)

# ループでReaderオブジェクトの行を順番に処理していく!
for row in example_reader:
  #各行はセルの文字列のリストになっている!
  #print()関数で現在の行番号と行内容を表示させる!行番号の取得にはReaderオブジェクトのline_num変数を使用する
  #line_num変数は行番号を表す変数!
  print('Row #' + str(example_reader.line_num) + '' + str(row))

せんぱい「Readerオブジェクトは1回しかループできないから、やり直したい場合はファイルを開き直すか、Fileオブジェクトのseek(0)を呼び出して先頭に戻してね!」

データをCSVに書き込め!Writerオブジェクト

データをCSVファイルに書き込むためにはどうしたら?
そんな問いに答えてくえるのがWriterオブジェクト。
Writerはライター、文章を書く人の意。
Writerオブジェクトを作成するには、csv.writer()関数を用いる。

せんぱい「はい、サンプルはこちらになります!」

import csv

output_file = open('output.csv', 'w', newline='')

output_writer = csv.writer(output_file)

output_writer.writerow(['spam', 'eggs', 'bacon', 'ham'])

output_writer.writerow(['Hello,world', 'eggs', 'bacon', 'ham'])

output_writer.writerow([1, 2, 3.141592, 4])

output_file.close()

上記コードび実行すると下記のようなcsvファイルを生成されます。

spam,eggs,bacon,ham
“Hellow, world!”,eggs,bacon,ham
1,2,3.141592,4

せんぱい「はい、ではくわしく見てみるよ~」

#まずはなにわともあれ、importモジュールを読み込む!
import csv

#まず、open()に'w'を渡して書き込みモードでファイルを開く
#Windowsだと、open関数にキーワード引数newlineに空文字を渡す必要がある
#なぜならこうしないと一行空きのCSVデータ作成される。その理由はとても難しい!
output_file = open('output.csv', 'w', newline='')

#このFileオブジェクトをcsv.writer()に渡してWriterオブジェクトを生成する
output_writer = csv.writer(output_file)

#.writerowメソッドはリストの引数をうけとる、リストの各要素の値が出力するCSVファイルのセルになる
#ちなみに、writerow()の戻り値はファイルに書き出した行の文字数になる!(改行を含む)
output_writer.writerow(['spam', 'eggs', 'bacon', 'ham'])

#Writeオブジェクトは「Hello,world!」の中のカンマをダブルクォートで自動的にエスケープしてくれる!
#便利!
output_writer.writerow(['Hello,world', 'eggs', 'bacon', 'ham'])

output_writer.writerow([1, 2, 3.141592, 4])

output_file.close()

カンマではなくタブで区切りたい!?はい、そんなときはキーワード引数delimiterとlineterminator

せんぱい「世の中、CSVではなくTSVなるものがある。
CSVではなく、TSVが欲しい、となったら?」

ガゼルさん「Trf?」

せんぱい「TSV!! Tetsuya Komuro Rave Factoryのことではなくて、Tab-Separeted Valuesね。カンマではなく、タブで区切られたファイルのことだよ」

import csv
csv_file = open('example.tsv', 'w', newline='')

csv_writer = csv.writer(csv_file,delimiter='\t',lineterminator='\n\n')

csv_writer.writerow(['apples', 'oranges', 'grapes'])

csv_writer.writerow(['eggs', 'bacon', 'ham'])

csv_writer.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])

csv_file.close()

せんぱい「このコードを実行すると、次のようなファイルexample.tsvが生成されるよ」

apples  oranges grapes

eggs  bacon  ham

spam  spam   spam  spam  spam 

せんぱい「はい、ではくわしくみていくよ!」

#なにわともあれcsvモジュールをインポート
import csv

#open()に'w'を渡して書き込みモードでファイルを開く
csv_file = open('example.tsv', 'w', newline='')

#区切り文字と行終端文字を変える!区切り文字は1行の中でセルの間にある文字。デフォルトではCSVファイルの区切り文字はカンマ!
#行終端文字は行末にある文字。デフォルトでは行終端文字は改行文字。
#csv.writer()キーワード引数delimiterとlineterminatorを使用すると、これたの文字を変更することができる!
#delimiterは区切り符号の意味。line terminatorで行末の意味
#delimiter='\t'とlineterminator='\n\n'とすることにより、セル間の文字がタブ・行間の文字は2つの改行文字となる
#\tはタブ、\nは改行を表すエスケープシーケンス。エスケープシーケンスは画面上に文字を出力しないけど、文字出力を制御する文字列のこと
#\n\nとしているので、2回改行している
csv_writer = csv.writer(csv_file,delimiter='\t',lineterminator='\n\n')

#writerow()を3回呼び出し3行書き込んでいる
csv_writer.writerow(['apples', 'oranges', 'grapes'])

csv_writer.writerow(['eggs', 'bacon', 'ham'])

csv_writer.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])

csv_file.close()

せんぱい「はい、これで!カンマがタブに、そして改行が2行入る形になったよ!」

ミッション! CSVファイルから見出しを削除する

数百個のCSVファイルから最初の行を削除するという退屈な作業を自動化する処理を作成しよう!

せんぱい「もし、こんな事を行うとして。
一回の作業自体はそんな大変ではないけれど。」

せんぱい「これを書くと…はい!こんな形になります!
ファイル名は removeCsvHeader.py になるよ」

#! python3
# removeCsvHeader.py - カレントディレクトリの全ファイルから見出しを削除する

import csv, os
os.makedirs('headerRemoved', exsit_ok=True)

# カレントディレクトリの全ファイルをループする
for csv_filename in os.listdir('.'):
  if not csv_filename.endswith('.csv')
    continue # CSVファイルでなければスキップ

  print('見出しの削除中'  + csv_filename + '...')

  #CSVファイルを読み込む(最初の行をスキップする)
  csv_row = []
  csv_file_obj = opne(csv_filename)
  reader_obj = csv.reader(csv_file_obj)
  for row in reader_obj
    if reader_obj.line_num == 1:
      continue # 最初の行をスキップする
    csv_rows.append(row)
  csv_file_obj.close()

  #CSVファイルを書き出す
  csv_file_obj = open(os.path.join('headerRemove', csv_filename), 'w', newline = '')
  csv_writer = csv.writer(csv_file_obj)
  for row in csv_rows:
    csv_writer.writerow(row)
  csv_file_obj.close()

せんぱい「はい、処理を順番にみていくよ~」

#! python3
# removeCsvHeader.py - カレントディレクトリの全ファイルから見出しを削除する

import csv, os

#まず、os.makedirs()を呼び出して見出しを削除したCSVファイルを書き込むheaderRemovedというフォルダの準備を行う
#os.listdir('.')について、forループを回す
#このままだとカレントディレクトリのすべてのファイルをループしてしまう..!
#だから、.csvで終わるファイル以外はスキップするコードを追加する!

os.makedirs('headerRemoved', exsit_ok=True)

# カレントディレクトリの全ファイルをループする
for csv_filename in os.listdir('.'):
  #もし、ファイル名の最後がcsvでなければ...!
  if not csv_filename.endswith('.csv')
    continue #スキップ!
  #実行状況が分かるように処理中のCSVファイル名を表示させる!
  print('見出しの削除中'  + csv_filename + '...')

#CSVファイルを読み込む(最初の行をスキップする) #Readerオブジェクトのline_num属性を使用すると、CSVファイルから現在読み込んでいる行番号がわかる csv_row = [] #CSVReaderオブジェクトを用意! csv_file_obj = opne(csv_filename) reader_obj = csv.reader(csv_file_obj) # こっちのforループでReaderオブジェクトが返す行をループして最初の行を除くすべての行をcsv_rowsに追加していく for row in reader_obj #もし最初の行だったらスキップ! if reader_obj.line_num == 1: continue # 最初の行をスキップする #最初の行じゃなかったらcsv_rowに行を追加していく!appendは追記の意 csv_rows.append(row) csv_file_obj.close()

せんぱい「ここまでで、csv_rowsに最初の行を除くすべての行が格納されたよ!
次は、実際にCSVファイルを書き出していくよ!」

#最初に作成したheaderRemovedフォルダにCSVファイルを作成して書き出していく

  #CSVファイルを書き出していく!
  #WriterオブジェクトはheaderRemoveフォルダの中にRederと同じcsv_filenameという名前のCSVファイルとしてcsv_rowsを書き込む
  #つまり、開いたCSVのファイル名と同じ名前で保存し直す
  csv_file_obj = open(os.path.join('headerRemove', csv_filename), 'w', newline = '')

  #Writerオブジェクトを作成!
  csv_writer = csv.writer(csv_file_obj)

  #csv_rowsをループして行をファイルに書き出す
  #書き出し処理が終わると、外側のforループがos.listdir('.')の次のファイルに書き出す
  #外側のループが終了すると、プログラムが完了する

  #行をファイルに書き出していく
  for row in csv_rows:
    csv_writer.writerow(row)
  csv_file_obj.close()

せんぱい「ファイルの内容を変更するにあたっては、必ずバックアップをとっておこうね~!」

類似プログラムのアイデア

せんぱい「CSVファイルを処理するプログラムはExcelファイルと同様のものを考えることができるよね!
だって似てるし!どちらもスプレッドシートだし!
アイデアとしては、下記のようなものが考えられるよね!」

  • CSVファイル内の異なる行の間のデータや、複数のCSVファイルの間のデータを比較する
  • CSVファイルからExcelファイルへ、またはその逆方向に特定のデータをコピーする
  • CSVファイル中の不正なデータや整形ミスを調べ、間違いをユーザーに通知する
  • Pythonプログラムの入力としてCSVからファイルを読み込む「

JSONとAPI

JSONは人間が読める文字列としてデータを整形するのによく使用される。
JSONはJavascriptプログラムがデータ構造を記述するネイティブな方法で、Pythonのpprint関数が生成するものに似ている。

せんぱい「まあ、ざっくり言うと、Javascriptでデータを扱う際に、JSONだと扱いやすいということだね!」

JSON形式のデータを扱うのに、Javascripotの知識は必要ない。
JSON形式に整形したデータの例

{"name": "Zophie", "isCat": true, "miceCaught": 0, "napsTaken": 37.5, "felineIQ": null}

JSONは多くのWebサイトがプログラムと通信する方式に採用されている。
このようなWebインターフェイスをAPI(アプリケーション・プログラミング・インターフェイス)という。

APIをアクセスするのはURLでWebページをアクセスするのと同じ。
違いは、APIが返すデータはコンピューターが読むためにJSONなどの形式に整形されていること。

APIの出力を人間が読むことは簡単ではない。

JSON形式のデータを提供しているサイトは多くあり、Facebook、Twitter、Yahoo、Google、Tumblrなどなど。
プログラムから使用できるAPIを提供している。

これらのサイトの中には登録が必要なものがあるが、ほとんど無料で使用することができる。
データを取得するためにプログラムがリクエストを送付するURLや、APIが返すJSONデータ構造の内容を知るためにはドキュメントを見つける必要がある。
こういったドキュメントはAPIの提供サイトに必ず用意されている。
「開発者用」や、「Developers」などのページがあればそこを探そう。

APIを使用することにより、下記のようなプログラムを作成することができる。

  • Webサイトの生データを取得する!(WebページをダウンロードしてBeautifulSoupでHTML解析するより、APIをアクセスするほうが便利なことが多い)
  • 自分のSNSアカウントひとつを使用し、新規投稿を自動ダウンロードし別のアカウントで投稿する。例えば、Tumblrの投稿を取得しFacebookに投稿する
  • 個人的な映画コレクションについてIMDbやRotten Tomatoesなどかデータを取得しひとつのテキストファイルにまとめて「映画辞典」を作成する

JSONを扱うためのjsonモジュールはどんな?

PythonのjsonモジュールはJSONデータの文字列とPythonの値との間を相互変換するあらゆる雑多な処理をjson.loads()とjson.dumps()関数により扱っている。

JSONはPythonのすべてのデータを保持しているわけではない。
JSONで記述できるのは文字列、整数、浮動小数点、ブール値、リスト、辞書、Noneだけ。
Fileオブジェクト、CSVのReaderやWriterオブジェクト、Regexオブジェクト、SeleniumのWebElementなどのPython特有のオブジェクトをJSONで表現することは難しい。

JSONを読み込むには?それにはloads()関数を使用するよ!

JSONデータを格納した文字列をPythonの値に変換するにはjson.loads()関数に渡す。
(この関数名は「load string」を意味する)。

string_of_json_data = '{"name": "Zopie", "isChat":true, "miceCaught": 0, "felineIQ": null}'
import json
json_data_as_python_value = json.loads(string.loads(string_of_json_data)
json_data_as_python_value

jsonモジュールをインポートした後はloads()にJSONデータを渡して呼び出すことができるようになる。
JSON文字列は常にダブルクォート(”)で囲む点に注意。
関数の戻り値はPythonの辞書型。
辞書型は順序を保持しない為、変換後のjson_data_as_python_valueを表示するとキー・バリュー・ペアの順番が元のJSON形式と異なる場合がある。

dumps()関数を用いてJSONを書き出す

json.dumps()関数)はPythonの値をJSON形式の文字に変換する。

python_value = {'isCat':True, 'miceCaught': 0, 'name': 'Zophie', 'felineIQ': None}
import json
string_of_json_data = json.dumps(python_value)
string_of_json_data

ミッション!JSONを使用して現在の天気予報データを取得してみよう!

せんぱい「次は、お天気情報を自動で取得するプログラムを作成してみよう!」

ガゼルさん「…アプリで見れるのに?」

せんぱい「そういう興覚めすることは言わないよ!
これから作成するプログラムはrequestsモジュールを用いてWebサイトからデータをダウンロードするものになります!
プログラム用に、quickWeather.pyという名前でファイルを作成して、いざ、書いていってみよう~!」

#! pythons3
# quickWeather.py -コマンドラインに指定した地名の天気予報を表示する

import json, requests, sys

# コマンドライン引数から地名を組み立てる

if len(sys.argv) < 2:
  print('Usage: quickWeather.py location')
  sys.exit()
location = ''.join(sys.argv[1])

# opennweathermap.orgから取得したAPIキーを定義しておく
APPID = '01234567890123456789012345678901'

#TODO: OpenWeatherMaps.orgのAPIデータからJSONデータをダウンロードする
url = 'http://api.openweathermap.org/data/2.5/forecast/daily?q={}&cnt=3&appid={}'.format(location,APPID)
response = requests.get(url)
response.raise_for_status\()

#TODO:JSONデータからPython変数に読み込む
weather_data = json.loads(response.text)
# 天気予報の情報を表示する
# weather_data['list']を変数wに格納して記述を省略している
w = weather_data['list']
print('{}の現在の天気:'.format(location))
print(w[0]['weather'][0]['main'], '_', w[0]['weather'][0]['description'])
print()
print('明日:')
print(w[0]['weather'][0]['main'], '_', w[1]['weather'][0]['description'])
print()
print('明後日:')
print(w[2]['weather'][0]['main'], '_', w[2]['weather'][0]['description'])

せんぱい「では、コードをくわしく見ていってみよう!」

ステップ1:コマンドライン引数から地名を取得する

#! pythons3
# quickWeather.py -コマンドラインに指定した地名の天気予報を表示する

#jsonモジュール、requestsモジュール、sysモジュールをインポートするぜ!
import json, requests, sys

#コマンドライン引数から地名を組み立てる
#コマンドライン引数はコマンドでファイルを呼び出した際に、受け継がれた値!
#Pythonではコマンドライン引数はリストsys.argvに格納されてる!
#シバン(#!)の行とimport文の後で、コマンドライン引数が2つ以上あるかどうかを調べる。
#(sys.argvには最低、1つの要素に対し、sys.argv[0]にPythonスクリプトのファイル名が必ず格納されている)。

if len(sys.argv) < 2:
  #もし、コマンドライン引数にファイル名しか入っていなかったら
  #おいおい!使い方を知らないのか!とUsage(使い方)のメッセージを表示してプログラムを終了する
  print('Usage: quickWeather.py location')
  #ここでプログラムを終了させる!
  sys.exit()

#もし、コマンドライン引数が2つ以上、住所として調べたい値が入っていたら!
#sys.argvの最初の要素を除いて結合、変数locationに格納する!

location = ''.join(sys.argv[1])

#ここから、JSONを使用して天気の情報を取得していくよ!
#活用するJSONデータはOpenWeatherMaps.orgのもの!
#OpenWeatherMaps.orgはリアルタイムの天気情報をJSON形式で提供している!
#例えば、天気予報を知りたい都市名を<Location>だとすると以下のデータをダウンロードするだけで済む。
#https://api.openweathermap.org/data/2.5/forecast/daily?q=<Location>&cnt=3&appid=<APPID>
#末尾のAPPIDはOpenWeatherMapから取得するAPIキー!つまり、APIを受け取るための鍵!
#この鍵をGETする方法は別途記載!

# ここに、opennweathermap.orgから取得したAPIキーをセット!
APPID = '01234567890123456789012345678901'


#では!OpenWeatherMaps.orgのAPIデータからJSONデータをダウンロードする
#ここに辿り着いたということは、コマンドライン引数から地名を取得できているということ!
#アクセスするURLの{}のプレースフォルダに地名を指定し、URLを組み立てる
#その結果をurlに格納し、requests.get()に渡す
url = 'https://api.openweathermap.org/data/2.5/forecast/daily?q={}&cnt=3&appid={}'.format(location,APPID)

#requests.get()を呼び出すと、Responseオブジェクトが返ってくる。
response = requests.get(url)

#さらにraise_for_status()を呼び出してエラーをチェックする。
response.raise_for_status()

#ここまできたら!例外が起きなければresponse.textにダウンロードしたテキストが格納されている。
#response.textにはJSON形式の巨大な文字列が格納されている。
#これをPythonの値に変換するためにはjson.loads()関数を呼び出す!
#変換後のデータをpprint.print()に渡すと、データを表示することができる!
#データフィールドの詳細説明は https://openweathermap.org/ に存在しているよ!

#JSONデータからPython変数に読み込む
weather_data = json.loads(response.text)

#オンラインドキュメントによると、'day'の後の302.29は摂氏や華氏ではなく、ケルビン単位の日中気温を表している。
#今回、必要なのはJSONデータの中の'main'と'description'の後の情報(おとしたJSONファイルの中の項目の一部/サンプルはのちほど)
#これらをきれいに表示する為、更に処理を実行していくよ!

# 天気予報の情報を表示していきまっせ!
# weather_data['list']を変数wに格納して記述を省略する!
#これでw[0]、w[1]、w[2]で、それぞれ今日、明日、明後日の天気の辞書を取得できる
w = weather_data['list']

print('{}の現在の天気:'.format(location))

#この辞書には'weather'というキーがあり、リストが格納されている。
#ここではインデックス0の最初の要素を用いて入れ子になった辞書を取得できる。
#そこから、'main'と'description'のキーに対応する値を取得・ハイフンで区切って表示する
print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description'])
print()#1行あける
print('明日:')
print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description'])
print()#1行あける
print('明後日:')
print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description'])

そこから’main’と’description’のキーに対応する値を取得し、ハイフンで区切り表示する。
「San Francisco, CA」というコマンドライン引数でこのプログラムを実行すると下記のように表示される。

San Francisco, CAの現在の天気:
Clear - sky is clear

明日:
Clouds - few clouds

明後日:
Clear sky is clear

作成したプログラムの流れ

  • コマンドラインから地名を読み込む
  • OpenWeatherMap.orgからJSON形式で天気予報データをダウンロードする
  • JSONデータ文字列をPythonデータ構造に変換する
  • 今日と明日、明後日の天気予報を表示する

コードが行っている処理

  • sys.argvの文字列を結合し地名を取得する
  • requests.get()を呼び出し天気予報データをダウンロードする
  • json.loads()を呼び出し、JSONデータをPythonのデータ構造に変換する
  • 天気予報を表示する

ツトム先輩のメモ!

せんぱい「コマンドライン引数はスペース文字で区切られているよ!
例えば、『San Francisco, CA』というコマンドライン引数を指定するとsys.argvには次のように格納されるよ」

[‘quickWeather.py’, ‘San’, ‘Fransisco’, ‘CA’]

はい!OpenWeatherMap.orgからAPIキーを取得する方法を見てみよう!

せんぱい「OpenWeatherMap.orgはリアルタイムの天気情報をJSON形式で提供しているサイトになるよ」

ガゼルさん「リアルタイムで提供…中の小人さん、大変ですね

せんぱい「中に小人さんがいるわけではないよ」

#その結果をurlに格納し、requests.get()に渡す
url = 'https://api.openweathermap.org/data/2.5/forecast/daily?q={}&cnt=3&appid={}'.format(location,APPID)

せんぱい「上記コードの、末尾で使用したAPPID。
この中にはAPIを使用するためのキー、もとい鍵が入っている。
ここで使用したAPPIDの取得方法についてみていくよ」

ガゼルさん「鍵、というからには何かをオープンする感じなんでしょうか?」

せんぱい「APIキーにアクセスする前に立ちはだかる、扉をオープンにするわけだねー」

ガゼルさん「心の扉ではなく!?

せんぱい「心のとびらではなく!」

OpenWeatherMapsからAPIキーを取得する流れ

  • OpenWeatherMaps
    openweathermap_Top

  • 1.https://openweathermap.org/home/sign_in へアクセス!
    上記画面にて、名前、メールアドレス、パスワードを入力し利用規約に同意するにチェックを入れ[Creater Account]をクリックする。
    openweathermap_Top

  • 2.ログインするとホーム画面が表示される。
    URL:https://home.openweathermap.org/api_keys
    openweathermap_Top

  • 3.[API Keys]をクリックするとAPI発行画面に切り替わる。
    既にデフォルトのキー(32文字の16進数)が発行されている為、これをコピーしてAPIキーとして用いる。
    openweathermap_Top
    ※APIキーの部分はぼかしてありマス。

PythonでCSVとJSONデータを編集する!のまとめ

せんぱい「CSVとJSONデータは、データを格納するために一般的に用いられるプレーンテキスト形式といえるよ」

ガゼルさん「プレーンテキスト。テキストエディタで中身を見ることができる形式、ってことですね!
プレーンといえばオムレツのイメージしかありませんでした!

せんぱい「ルロイ修道士が残しちゃうやつ!
CSVとJSONは、特性としてプログラムから解析するのが容易でありながら、人間が読むこともできる。
この点が大きいよね!」

ガゼルさん「人が読むことができないと、何かやろうとした時にやっぱり大変ですもんね
まあ、ぼくはガゼルですけど

せんぱい「…!ま、まぁCSVとJSONファイルはその特性から、簡単なスプレッドシートやWebアプリケーションのデータとしてよく用いられてきたよ。
csvとjsonモジュールを用いると、CSVとJSONファイルを読み書きする処理を非常に簡単にできちゃうよね!」

ガゼルさん「やりたいことがそろってましたブイ!」

せんぱい「何その語尾!
さまざまなファイル形式から情報を解析して用いる方法はあるけど、共通する作業はさまざまなファイル形式からデータを読み込んで解析し、必要な情報を取り出すということだよね!」

ガゼルさん「ですね、読み込んでまぜたりひねったりしてましたブイ!」

せんぱい「もう既にあるソフトウェアでも出来たりすることもあるけれど、小回りが効かなかったりする
そういうときに、自身でそういったプログラムをつくれると便利でしょ?」

ガゼルさん「小回り聞きそうですブイ!」

せんぱい「自身でスクリプトを書くと、こんなフォーマットで表された大量のデータを、自身がやりたいように編集することができる!
ぜひ、試してみて!」

ガゼルさん「シー・エス・ブイ!!」

せんぱい「CSV!さいごに、改めて今回の内容で参考にさせてもらったのは下記記事になります!
ぜひ、そちらの書籍も併せてご検討ください!」

%d人のブロガーが「いいね」をつけました。