『退屈なことはPythonにやらせよう』その12(14章:CSVとJSON)

Python初心者です。『退屈なことはPythonにやらせよう』を走っています。

12回目の今回は、14章をやっていきます~。

PyPDF2とpython-docxを使って、PDFとWordファイルをいじった前回の記事はこちら↓

今回の目次


1. CSVモジュール

CSVファイルは、シンプルなExcelシート

CSVファイルの「CSV」は「Comma Separated Values」の略です。訳すなら「カンマによって分けられた値」、もっと気合をいれるなら、「カンマによって隔絶されし値達」といったところでしょうか。いずれにせよ、それぞれの値(CSVファイル中ではただの文字列)が、カンマ(やタブなどのいくつかのセパレータとして認識される特定の記号)によって分けられたデータです。基本的に、値がプレーンテキストで書かれています。

CSVファイルの特徴は以下の通りになります。

  • 全てが文字列
  • フォントに色やサイズがない
  • ワークシートは1枚だけ
  • セルの幅と高さを指定できない(データを区切り文字で区切って記録するだけ)
  • 画像は入らない

Excelと違って、シンプルな分、多くの種類のプログラムでサポートされています。CSVと言っても、値の中にカンマを含みたい場合にも対応できるように、カンマ以外でデータの切れ目を指定することができます。そのため、CSVファイルを扱うにはpythonの標準モジュールであるcsvモジュール(もしくはサードパーティ製のpandasやnumpy)で扱うことが主流となっています。

csvモジュールの基本の使い方

csvモジュールの基本の使い方は以下の通りです。

csvモジュールを使ったデータの読み込み

  • csv モジュールのインポート
  • open()でcsvファイルを開く
  • csv.reader()にopen()で開いたファイルオブジェクトを渡す→Readerオブジェクト
    (Readerオブジェクトをlist()に渡すと値を取得できる)
  • データの取り出しは data[row][col]
  • Readerオブジェクトにline_num変数を与えると、行番号が取得できる

csvモジュールを使ったデータの書き込み

  • csvモジュールのインポート
  • open(“ファイル”, “w”, newline = “”)として新しいファイルを開く
  • csv.writer()にopen()で開いたファイルオブジェクトを渡す(deliminaterとlineteriminatorもここで指定)→Writerオブジェクト
  • Writerオブジェクトに対して writerow(リスト)とすると、リストの値が同じ行に書き込まれる
  • 書き込みが終わったらファイルオブジェクトをclose()

deliminaterとlineterminatorは、データの間の区切りの目印になる記号と、行を変更する際に目印になる記号のことです。

  • deliminater : データの値の区切りとなる記号(ex. カンマ)
  • lineterminator:データを入力する行を切り替える時の目印となる記号(ex. “\n”)

2. JSONモジュール

JSONファイルはWebから情報をとってくるのに便利な形式

JSONファイルは「JavaScript Object Notation」の略です(json.org)。人間にとっても、機会にとっても、とっても読み書きが楽なファイル形式です。JavaScriptがデータ構造を記述する言語ではありますが、JavaScript自体が書けなくてもそのデータを利用することはできます。

API(Application Programming Interface)から返ってくるデータはJSON方式が採用されている場合が多いようです。

ちなみに大塚商会のIT用語辞典によると、APIとは

Application Programming Interfaceの略。ソフトウェアからOSの機能を利用するための仕様またはインターフェースの総称で、アプリケーションの開発を容易にするためのソフトウェア資源のことをいう。「API」の重要な役割は、サービス提供者が公式に仕様を定義・管理している操作方法(インターフェース)を提供することである。

https://www.otsuka-shokai.co.jp/words/api.html

ということです。ウェブサービスと、OS、つまりはパソコンやスマホのシステムの橋渡し的な存在という感じでしょうか?JSON方式のを活用して、アプリのAPIから様々なデータを取得し、利用することが可能になります。それでは、JavaScriptがよく分からなくても、JSONデータを処理することが出来るようにしてくれる、jsonモジュールを見ていきます。

jsonモジュールの基本の使い方

jsonモジュールはPythonの標準モジュールの一つです。そのままimport jsonとすれば使用することができます。ただし、扱えるデータ形式が限られています。

jsonで記述できるもの

  • 文字列
  • 整数
  • 浮動小数点数
  • ブール値
  • リスト
  • 辞書
  • None

だけになります。

WebAPIを使うことになるので、対象のAPIのキーを取得しておくことが前提となります。本の中では、「OpenWeatherMap.org」が例として紹介されています。APIキーをゲットしてからすぐにコードを実行したのですが、Autorizationエラーとなってしまいました(エラー401)。ヘルプに飛んでみると、キーを発行してから数時間かかる時もありますとのことでした。

それはさておき、JSONモジュールの基本の使い方の流れは以下の通りです。

  • jsonモジュールをインポート
  • APIキーを、提供されている場所から取得する
  • APIキーを含むサイトのURLに対して、requests.get(URL)として、データを取得する→Requestsオブジェクト
  • json.load(Requestsオブジェクト.text)
  • Print()などを用いて、データの形に合わせて、欲しいデータを出力する

APIの仕様はサービスによって違うので、提供しているサイトのAPIの使い方ガイドみたいなやつを見ましょう。そこで、Requests.get()に渡すURLの型(書式?)も提供されています。また、JSONデータがどのような形のデータになっているかの例も、そこで書いてある場合があります。書き出すときの参考にしましょう。


3. 14章演習プロジェクト

ExcelファイルからCSVへの変換

今回は演習プロジェクトが一つです!(12章には5個もあったのに!)
内容としては、複数のシートを持つExcelファイルをそれぞれのファイル名とシート名が分かる名前のcsvファイルとして保存するというものです。

今回は課題が一つなだけでなく、ひな形と練習用のファイルまで準備してあります。これは楽勝ですね。

日本語版のGitHub上に、テスト用のファイルがありますよ~ってなってたのですが、展開してみたら全部CSVファイルだったので、まずは自分でExcelシートを生成するコードを書きました。

#! python3
# check14_1.py  -  複数のシートを持つExcelファイルを生成する

#debug
import logging
logging.basicConfig(level=logging.DEBUG,
format = " %(asctime)s - %(levelname)s - %(message)s")
logging.debug("プログラム開始")
#logging.disable(logging.CRITICAL)

import openpyxl, os

logging.debug("フォルダを作成")
os.makedirs("nyankos", exist_ok=True)

logging.debug("ファイルを作成")
for i in range(10):
    wb = openpyxl.Workbook()
    sheet = wb["Sheet"]
    sheet1 = wb.create_sheet("sheet1")
    sheet2 = wb.create_sheet("sheet2")
    for j in range(1, 11):
        for k in range(1, 11):
            sheet.cell(row=j, column=k).value = "{}番目のnekosan{:3}".format(j, i)
            sheet1.cell(row=j, column=k).value = "{}番目のneko{:3}".format(j, i)
            sheet2.cell(row=j, column=k).value = "{}番目のcat{:3}".format(j, i)
    wb.save(os.path.join("nyankos","nyanko{:3}.xlsx".format(i)))
    logging.debug("nyanko{}.xlsxを生成しました".format(i))

logging.debug("プログラム終了")

コードを実行すると、こんな感じのExcelファイルが生成されます。

result_pre_check14_1.py

若干の狂気をまとっているような気もしますが、練習用に生成しただけのシートなのでこんなもんでいいでしょう。sheet1とsheet2も同じような感じになっています。

課題のコードは以下の通りです。

#! python3
# check14_1.py  -  ExcelファイルをCSVに変換する 

#debug
import logging
logging.basicConfig(level=logging.DEBUG,
format = " %(asctime)s - %(levelname)s - %(message)s")
logging.debug("プログラム開始")
#logging.disable(logging.CRITICAL)

import csv, openpyxl, os

os.chdir("nyankos")   #Excelファイルの入っているディレクトリにカレントディレクトリを移動

for excel_file in os.listdir("."):
    if not excel_file.endswith(".xlsx"):
        continue
    else:
        wb = openpyxl.load_workbook(excel_file)
    for sheet_name in wb.get_sheet_names():
        
        sheet = wb.get_sheet_by_name(sheet_name)

        #Excelファイル名とシートファイル名からCSVファイル名を作る

        #このCSVファイル用にcsv.writerオブジェクトを作る
        output_file = open("{}_{}.csv".format(excel_file[:-5], sheet_name), "w", newline="")
        output_writer = csv.writer(output_file)
        #シートの行をループする
        for row_num in range(1, sheet.max_row +1):
            row_data = []
            #行のセルをループする
            for col_num in range(1, sheet.max_column+ 1):
                #セルをrow_dataに格納する
                values = sheet.cell(row=row_num, column=col_num).value
                row_data.append(values)
                logging.debug("セルの値は{}".format(values))
            
            #row_dataをCSVファイルに書き出す
            output_writer.writerow(row_data)
        output_file.close()
    
logging.debug("プログラムが終了しました。")

セルの値を順番にリストに格納して、そのリストをwriterow(リスト)で一気に渡しています。

順番に解説しておくと

  1. ディレクトリを変更(ファイルの名前をちゃんとパスにすれば必要無し)
  2. ファイル全部をリストとして取得しつつ、.xlsxの時だけ書き出すようにする
  3. それぞれCSVとして新しいファイルを用意する(ファイルの名前は「<Excelファイルの名前>_<シートの名前>.csv」)
  4. シートのrowとcolumnの最大値を取得しながら、rowごとにリストを作成
  5. row_listをwriterow()で新しいCSVファイルに書き出す

と言う感じです。長そうに見えて、意外と大したことはしてないんですね。


4. 感想

今回はCSVとJSONについて学びました。JSONを使いこなすには本書だけだと厳しいですね。CSVにしても、Pandasなどもあるので、CSVモジュールだけに頼らない方法も模索しつつ、CSVモジュールも便利に使っていきたいと思います。

次の記事はこちらです↓

『退屈なことはPythonにやらせよう』その12(14章:CSVとJSON)” に対して3件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です