基礎から学ぶPython入門 90日コース | Web・API - Day 56:Webデータ保存

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

Day 56:Webデータ保存 ― 「集めた情報」をちゃんと残せる形にする

Day 56では、これまでに取得してきた Webデータを保存する方法 を整理していきます。

テーマはこの3つです。

  • CSV
  • JSON
  • SQLite

どれも「よく使われる保存形式」ですが、 それぞれ得意な場面が少しずつ違います。

今日は、同じデータを3つの形式に保存してみる ことで、 「どんなときにどれを選ぶと気持ちよく使えるか」を体感していきます。

Webデータの例を決める:シンプルな「検索結果データ」

まずは、保存する対象となるデータの形を決めます。

ここでは、次のような「検索結果データ」を例にします。

  • title:結果のタイトル
  • url:リンク先のURL
  • snippet:簡単な説明文(なければ空文字でもOK)

Pythonでは、こんな感じのリストで持っているイメージです。

# day56_sample_data.py

# Webから取得したと仮定する検索結果データの例です。
search_results = [
    {
        "title": "Python公式ドキュメント",
        "url": "https://docs.python.org/ja/3/",
        "snippet": "Pythonの公式リファレンスとチュートリアルです。",
    },
    {
        "title": "Requestsライブラリ入門",
        "url": "https://requests.readthedocs.io/",
        "snippet": "PythonでHTTP通信を行うための人気ライブラリです。",
    },
    {
        "title": "Beautiful Soupによるスクレイピング",
        "url": "https://www.crummy.com/software/BeautifulSoup/",
        "snippet": "HTML解析ライブラリ Beautiful Soup の公式ページです。",
    },
]
Python

この search_results を、 CSV・JSON・SQLiteの3つに保存していく流れで説明していきます。

CSV保存:表形式で「Excelと仲良く」使いたいとき

CSVとは何か

CSVは、カンマ区切りのテキストファイル です。

  • 1行が1レコード
  • カンマで項目を区切る
  • 1行目にヘッダー(列名)を書くことが多い

というシンプルな形式で、 Excelやスプレッドシートと相性が良いのが特徴です。

PythonでCSVに保存する基本パターン

Pythonには標準で csv モジュールが用意されていて、 辞書のリストをそのままCSVに書き出すことができます。

# day56_save_csv.py
import csv


def save_to_csv(results: list[dict], filename: str) -> None:
    """
    検索結果データをCSVファイルに保存する関数です。
    - results: 辞書のリスト(title, url, snippet を想定)
    - filename: 保存するCSVファイル名
    """

    # 保存したい列の順番を定義します。
    fieldnames = ["title", "url", "snippet"]

    print(f"[CSV] {filename} に保存します。")

    # newline="" を指定することで、余計な空行が入るのを防ぎます。
    with open(filename, mode="w", encoding="utf-8", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)

        # 1行目にヘッダーを書きます。
        writer.writeheader()

        # 各結果を1行ずつ書き込みます。
        for item in results:
            writer.writerow(item)


if __name__ == "__main__":
    # サンプルデータを読み込みます。
    from day56_sample_data import search_results

    save_to_csv(search_results, "search_results.csv")
Python

ポイント:

  • csv.DictWriter を使うと、辞書のキーを列名として扱えます。
  • writeheader() でヘッダー行を書いておくと、Excelで開いたときに分かりやすくなります。
  • newline="" を指定するのは、Windows環境で余計な空行が入るのを防ぐための定番テクニックです。

CSVは、

  • 人が目で見て確認したい
  • Excelで編集したい
  • シンプルな表形式で十分

という場面でとても使いやすい形式です。

JSON保存:構造をそのまま「プログラム同士で」やり取りしたいとき

JSONとは何か

JSONは、「辞書+リスト」をそのままテキストにしたような形式 です。

  • オブジェクト → Pythonの辞書に近い
  • 配列 → Pythonのリストに近い

という構造を持っていて、 Web APIの世界ではほぼ標準のデータ形式になっています。

PythonでJSONに保存する基本パターン

Pythonには標準で json モジュールがあり、 辞書やリストをそのままJSONに変換して保存できます。

# day56_save_json.py
import json


def save_to_json(results: list[dict], filename: str) -> None:
    """
    検索結果データをJSONファイルに保存する関数です。
    - results: 辞書のリスト
    - filename: 保存するJSONファイル名
    """

    print(f"[JSON] {filename} に保存します。")

    # ensure_ascii=False を指定すると、日本語もそのまま保存されます。
    # indent=2 を指定すると、読みやすい整形されたJSONになります。
    with open(filename, mode="w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=2)


if __name__ == "__main__":
    from day56_sample_data import search_results

    save_to_json(search_results, "search_results.json")
Python

ポイント:

  • json.dump() で、PythonのオブジェクトをそのままJSONに書き出せます。
  • ensure_ascii=False を付けると、日本語が \uXXXX ではなくそのまま保存されます。
  • indent=2 で、改行とインデントが付いた「読みやすいJSON」になります。

JSONは、

  • 他のプログラムやサービスとデータをやり取りしたい
  • Web APIのレスポンスをそのまま保存したい
  • ネストした構造(入れ子の辞書やリスト)を保ちたい

という場面でとても便利な形式です。

SQLite保存:小さな「データベース」として扱いたいとき

SQLiteとは何か

SQLiteは、ファイル1つで完結する軽量なデータベース です。

  • サーバーを立てなくても使える
  • 1つの .db ファイルにテーブルを作ってデータを保存できる
  • SQL(SELECT, INSERT, UPDATEなど)で柔軟に検索・集計できる

という特徴があり、 「ちょっとしたデータをちゃんと管理したい」ときにぴったりです。

PythonでSQLiteに保存する基本パターン

Pythonには標準で sqlite3 モジュールがあり、 これを使ってSQLiteデータベースに接続・操作できます。

# day56_save_sqlite.py
import sqlite3


def init_db(db_name: str) -> None:
    """
    SQLiteデータベースを初期化する関数です。
    - テーブルがなければ作成します。
    """

    print(f"[SQLite] データベース {db_name} を初期化します。")

    # データベースファイルに接続します(なければ作成されます)。
    conn = sqlite3.connect(db_name)
    cursor = conn.cursor()

    # 検索結果を保存するためのテーブルを作成します。
    # IF NOT EXISTS を付けることで、既にある場合はエラーになりません。
    cursor.execute(
        """
        CREATE TABLE IF NOT EXISTS search_results (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL,
            url TEXT NOT NULL,
            snippet TEXT
        )
        """
    )

    conn.commit()
    conn.close()


def save_to_sqlite(results: list[dict], db_name: str) -> None:
    """
    検索結果データをSQLiteデータベースに保存する関数です。
    - results: 辞書のリスト
    - db_name: データベースファイル名
    """

    print(f"[SQLite] {db_name} にデータを保存します。")

    conn = sqlite3.connect(db_name)
    cursor = conn.cursor()

    # 1件ずつINSERTしていきます。
    for item in results:
        cursor.execute(
            """
            INSERT INTO search_results (title, url, snippet)
            VALUES (?, ?, ?)
            """,
            (item["title"], item["url"], item["snippet"]),
        )

    conn.commit()
    conn.close()


def fetch_all_results(db_name: str) -> None:
    """
    保存された検索結果をすべて取得して表示する関数です。
    SQLiteにちゃんと保存されているか確認するための例です。
    """

    print(f"[SQLite] {db_name} からデータを読み込みます。")

    conn = sqlite3.connect(db_name)
    cursor = conn.cursor()

    cursor.execute("SELECT id, title, url, snippet FROM search_results")
    rows = cursor.fetchall()

    print(f"保存されている件数: {len(rows)}")
    print("\n=== 保存済み検索結果一覧 ===")
    for row in rows:
        id_, title, url, snippet = row
        print(f"[{id_}] {title} ({url})")
        if snippet:
            print(f"    {snippet}")

    conn.close()


if __name__ == "__main__":
    from day56_sample_data import search_results

    db_file = "search_results.db"

    init_db(db_file)
    save_to_sqlite(search_results, db_file)
    fetch_all_results(db_file)
Python

ポイント:

  • sqlite3.connect(db_name) で、データベースファイルに接続します。
  • CREATE TABLE IF NOT EXISTS で、テーブルがなければ作成します。
  • INSERT INTO ... VALUES (?, ?, ?)? に、タプルで値を渡します(プレースホルダ)。
  • SELECT で保存されたデータを読み出し、ちゃんと保存できているか確認できます。

SQLiteは、

  • データを長期的に蓄積したい
  • 条件検索や集計を柔軟に行いたい
  • 複数のテーブルを使って少し複雑なデータ構造を扱いたい

という場面でとても頼りになる存在です。

3つの保存形式を並べて考える

ここまでで、

  • CSV:表形式で人間やExcelと仲良くしたいとき
  • JSON:構造を保ったままプログラム同士でやり取りしたいとき
  • SQLite:小さなデータベースとして柔軟に検索・集計したいとき

というイメージが見えてきたと思います。

同じ search_results を3つの形式に保存しておくと、

  • CSV → ざっと眺めたい・Excelで編集したい
  • JSON → 他のツールやAPIと連携したい
  • SQLite → 後から「特定のキーワードを含むタイトルだけ」などの検索をしたい

といった使い分けができるようになります。

Day 56ミニテンプレート:Webデータ保存の「まとめスクリプト」

最後に、Day 56の内容をひとつにまとめた 「Webデータ保存まとめスクリプト」 を載せておきます。

# day56_save_all.py
from day56_sample_data import search_results
from day56_save_csv import save_to_csv
from day56_save_json import save_to_json
from day56_save_sqlite import init_db, save_to_sqlite, fetch_all_results


def main():
    print("Webデータ保存デモを開始します。")

    # 1. CSVに保存
    save_to_csv(search_results, "search_results.csv")

    # 2. JSONに保存
    save_to_json(search_results, "search_results.json")

    # 3. SQLiteに保存
    db_file = "search_results.db"
    init_db(db_file)
    save_to_sqlite(search_results, db_file)
    fetch_all_results(db_file)

    print("Webデータ保存デモを終了します。")


if __name__ == "__main__":
    main()
Python

このスクリプトを実行すると、

  • search_results.csv
  • search_results.json
  • search_results.db

の3つが生成されて、 それぞれの形式で同じデータが保存されていることを確認できます。

Day 56のまとめ

Day 56では、Webデータ保存の基礎として、

  • Webから取得したデータを「辞書のリスト」として扱う前提を整理し
  • CSVに保存して、表形式で人間やExcelと仲良くできる形にする方法
  • JSONに保存して、構造を保ったままプログラム同士でやり取りできる形にする方法
  • SQLiteに保存して、小さなデータベースとして柔軟に検索・集計できる形にする方法

を、コード例とともにステップバイステップで確認しました。

この土台があると、

  • Webから定期的に取得したデータを蓄積して分析する
  • APIレスポンスをそのままJSONで保存して後から再利用する
  • 業務自動化ツールで集めたログや結果をSQLiteにためてレポートを作る

といった「データを活かす」方向へ、 自然にステップアップしていけるようになります。

タイトルとURLをコピーしました