【Python講座 第7回】ファイル操作とスクレイピング完全攻略。VPSでデータを収集・保存・ログ管理する技術

データは「保存」して初めて「資産」になる。

こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回(第6回)は、外部ライブラリ(requests)を使って、Web上のデータを取得する方法を学びました。
しかし、今のままではプログラムを終了すると、せっかく集めたデータはメモリから消えてなくなってしまいます。

「集めたデータをExcelで見たい」
「エラーが起きた日時を記録に残したい」
「毎日ニュースサイトを巡回して、記事タイトルを保存したい」

これらを実現するためには、「ファイル操作(読み書き)」「ログ管理」の技術が不可欠です。
さらに今回は、Webサイトから必要な情報だけを抜き出す「スクレイピング」という強力な技術も伝授します。

コウ君

先生、VPSにログインしました!
スクレイピングって聞いたことあります! 自動で情報を集めるやつですよね?
でも、やりすぎると相手のサーバーを落としちゃうって聞いたことがあって…。
やっぱり危険な技術なんですか?

リナックス先生

その通り、コウ君。「力には責任が伴う」のよ。
スクレイピングは便利だけど、一歩間違えれば「サイバー攻撃」とみなされることもあるわ。
今回は技術だけでなく、エンジニアとして絶対に守るべき「スクレイピングのマナーとアクセス制御」についても厳しく指導するわね。

本記事では、Python初心者にとって最適な勉強方法である「実機(VPS)でのコーディング」を通して、データの保存と収集技術を完全にマスターします。


1. ファイル操作の基本:読み込みと書き込み

Pythonでファイルを扱う際の基本構文は open() 関数ですが、実務では必ず with 構文と組み合わせて使います。

なぜ with を使うのか?

ファイルを開いたら、必ず「閉じる(close)」必要があります。
閉じ忘れると、メモリリークを起こしたり、ファイルが壊れたりします。
with 構文を使うと、ブロックを抜けた時に自動的にファイルを閉じてくれるため、安全性が格段に向上します。

1-1. 仮想環境の有効化

いつものように、VPS(AlmaLinux 9)に接続し、仮想環境に入ります。

cd ~/python_study
source .venv/bin/activate

1-2. テキストファイルの書き込み(write)

file_write.py を作成します。

# 'w' は書き込みモード(上書き)
# encoding='utf-8' を指定するのがプロの作法
with open("test.txt", "w", encoding="utf-8") as f:
    f.write("Hello, File World!\n")
    f.write("これはテスト書き込みです。\n")

print("書き込み完了")

実行後、ls コマンドで test.txt が出来ていることを確認し、cat test.txt で中身を見てみましょう。

1-3. テキストファイルの読み込み(read)

file_read.py を作成します。

# 'r' は読み込みモード(省略可能)
try:
    with open("test.txt", "r", encoding="utf-8") as f:
        content = f.read()
        print("--- ファイルの中身 ---")
        print(content)
except FileNotFoundError:
    print("ファイルが見つかりません。")

💡 プロのノウハウ:文字コード問題
Windows環境では、デフォルトの文字コードが cp932 (Shift-JIS) になることがあります。
Linux(UTF-8)との互換性を保つため、open() 関数では必ず encoding="utf-8" を明示するのが鉄則です。


2. 実践:CSVファイルの読み書き

実務で扱うデータの大半は、Excelでも開ける CSV形式 です。
Pythonには標準で強力な csv モジュールがあります。

2-1. リストデータをCSVに保存する

csv_write.py を作成します。
newline='' オプションは、Windowsで余計な空行が入るのを防ぐために必要です。

import csv

# 保存したいデータ(リストのリスト)
data = [
    ["ID", "名前", "スコア"],
    [1, "コウ君", 85],
    [2, "リナックス先生", 98],
    [3, "パイソン", 70]
]

with open("score.csv", "w", encoding="utf-8", newline='') as f:
    writer = csv.writer(f)
    writer.writerows(data)

print("CSV保存完了")

2-2. CSVを辞書として読み込む

ヘッダー行(1行目)をキーとして扱えると便利です。DictReader を使います。
csv_read.py を作成します。

import csv

print("--- スコア一覧 ---")
with open("score.csv", "r", encoding="utf-8") as f:
    # 辞書形式で読み込むリーダー
    reader = csv.DictReader(f)
    
    for row in reader:
        # ヘッダー名("名前", "スコア")でアクセスできる
        name = row["名前"]
        score = row["スコア"]
        print(f"{name}さんのスコア: {score}点")

実行結果:

--- スコア一覧 ---
コウ君さんのスコア: 85点
リナックス先生さんのスコア: 98点
パイソンさんのスコア: 70点

3. スクレイピング基礎:BeautifulSoup4の導入

Webページ(HTML)から特定の情報だけを抜き出す技術をスクレイピングと呼びます。
ここでは、最も有名なライブラリ BeautifulSoup4 を使用します。

3-1. ライブラリのインストール

仮想環境内でインストールします。

pip install beautifulsoup4 requests

3-2. HTML解析の実験

Python公式サイトのニュースタイトルを取得してみましょう。
scrape_test.py を作成します。

import requests
from bs4 import BeautifulSoup

url = "https://www.python.org/"

# Webページを取得
response = requests.get(url)

# HTMLを解析できる状態にする(パース)
soup = BeautifulSoup(response.text, "html.parser")

print("--- Python.org 最新ニュース ---")

# CSSセレクタを使って要素を探す
# .blog-widget li a -> class="blog-widget"の中のliの中のaタグ
news_list = soup.select(".blog-widget li a")

for news in news_list[:5]:  # 最新5件だけ
    title = news.text
    link = news.get("href")
    print(f"タイトル: {title}")
    print(f"リンク: {link}")
    print("-" * 20)

実行すると、Python公式サイトの最新ニュースタイトルとリンクが抽出されます。
soup.select() にCSSセレクタを渡すだけで、特定の要素をリストとして取得できます。


4. プロの常識:スクレイピングのマナーとtime.sleep

スクレイピングは「相手のサーバーに負荷をかける行為」です。
プログラムは人間よりはるかに高速にアクセスできるため、一歩間違えると攻撃(DoS攻撃)とみなされ、IPアドレスをブロックされたり、法的措置を取られたりするリスクがあります。

絶対に守るべき3つのルール

  1. アクセス間隔を空ける (time.sleep):
    連続アクセスする際は、必ず最低1秒(推奨3秒以上)の待機時間を入れます。
  2. robots.txt を確認する:
    https://example.com/robots.txt にアクセスし、スクレイピングが禁止されていないか確認します。
  3. User-Agent を設定する:
    「誰がアクセスしているか」を明示します。

マナーを守ったループ処理の例

import time
import random

urls = ["http://example.com/page1", "http://example.com/page2", "http://example.com/page3"]

for url in urls:
    print(f"アクセス中: {url}")
    # requests.get(url) ... 処理
    
    # 処理が終わったら必ず待機!
    # 2秒〜4秒のランダムな時間待機すると、機械的な挙動に見えにくい
    wait_time = random.uniform(2, 4)
    print(f"{wait_time:.2f}秒 待機します...")
    time.sleep(wait_time)

⚠️ 警告
for ループや while ループの中で requests.get を行う場合、time.sleep を入れ忘れると、1秒間に数十回のリクエストが飛び、即座にBANされる可能性があります。
VPSはネットワーク回線が太いため、自宅PCよりもさらに危険です。十分に注意してください。


5. 「print」からの卒業:loggingモジュール

これまでは print() で結果やエラーを表示してきましたが、自動化システムでは画面を見る人がいません。
動作状況をファイルに記録する「ログ(Log)」が重要になります。

5-1. loggingの基本設定

log_test.py を作成します。

import logging

# ログ設定
logging.basicConfig(
    filename='app.log',       # ログファイル名
    level=logging.INFO,       # 記録するレベル(INFO以上)
    format='%(asctime)s - %(levelname)s - %(message)s', # 日時-レベル-内容
    encoding='utf-8'
)

logging.info("プログラムを開始しました。")
logging.debug("これは記録されません(レベルが低いので)")

try:
    x = 10 / 0
except ZeroDivisionError as e:
    logging.error(f"エラーが発生しました: {e}")

logging.info("プログラムを終了しました。")

5-2. 実行とログ確認

python log_test.py
cat app.log

app.log の内容例:

2026-02-12 12:00:01,123 - INFO - プログラムを開始しました。
2026-02-12 12:00:01,125 - ERROR - エラーが発生しました: division by zero
2026-02-12 12:00:01,126 - INFO - プログラムを終了しました。

print と違い、いつ(日時)、何が(エラー内容)起きたかが自動的に記録されます。
「動かない!」となった時、エンジニアはまずこのログを見ます。


6. 演習問題:ニュース収集&ログ保存ボット

今回の総仕上げです。
Python公式サイトのニュースを取得し、CSVに保存しつつ、動作ログを残すプログラムを作成しましょう。
これができれば、立派な「クローラー(収集ボット)」開発者です。

【課題】

  1. Python.orgのニュース(.blog-widget li a)を取得する。
  2. 取得したデータ(タイトル、URL)を python_news.csv に追記モード(a)で保存する。
  3. 処理の開始、取得件数、エラーなどを crawler.log に記録する。
  4. time.sleep は今回は1回きりのアクセスなので不要だが、意識しておく。

解答例 (news_crawler.py)

import requests
from bs4 import BeautifulSoup
import csv
import logging
import datetime

# ログ設定
logging.basicConfig(
    filename='crawler.log',
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    encoding='utf-8'
)

def save_to_csv(data_list):
    """ データをCSVに追記保存する関数 """
    try:
        with open("python_news.csv", "a", encoding="utf-8", newline='') as f:
            writer = csv.writer(f)
            # 今日の日付も一緒に保存
            today = datetime.date.today()
            for title, url in data_list:
                writer.writerow([today, title, url])
        logging.info(f"{len(data_list)}件のデータをCSVに保存しました。")
    except Exception as e:
        logging.error(f"CSV保存エラー: {e}")

def main():
    logging.info("クローラー処理開始")
    url = "https://www.python.org/"
    
    try:
        response = requests.get(url)
        response.raise_for_status() # エラーチェック
        
        soup = BeautifulSoup(response.text, "html.parser")
        news_elements = soup.select(".blog-widget li a")
        
        extracted_data = []
        for news in news_elements[:5]: # 最新5件
            title = news.text.strip()
            link = news.get("href")
            extracted_data.append([title, link])
            
        logging.info(f"Webサイトから{len(extracted_data)}件取得しました。")
        
        # CSV保存関数を呼び出す
        save_to_csv(extracted_data)
        
    except Exception as e:
        logging.error(f"スクレイピング中にエラー発生: {e}")
    
    logging.info("クローラー処理終了")

if __name__ == "__main__":
    main()

実行後、crawler.logpython_news.csv が生成されていることを確認してください。
CSVには日付も入るようにしたので、このプログラムを毎日動かせば、日々のニュースが蓄積されていきます。


まとめ:データエンジニアへの入り口

お疲れ様でした! 第7回では、データを「集めて」「保存して」「記録する」という、実用的なアプリケーション開発の核心部分を学びました。

今回の達成項目:

  • open()with 構文を使った安全なファイル操作を習得した。
  • csv モジュールで構造化データを読み書きできた。
  • BeautifulSoup4 を使ってWebページから情報を抽出した。
  • スクレイピングにおけるアクセス間隔(time.sleep)の重要性を理解した。
  • logging モジュールを使って、プロ仕様のログ管理を実装した。

これで、あなたのプログラムは単なる計算機を超え、外部の世界から情報を集め、資産として蓄積するシステムへと進化しました。

次回はいよいよ最終回。ここまで作ったプログラムを、あなたが寝ている間も自動で動かし続ける「完全自動化システム」へと昇華させます。
Linuxの機能 Cron を使った定期実行の設定方法を学びましょう。

次回、【第8回】自動化システム構築:定期実行(Cron)でボットを作成する でお会いしましょう!

▼ Pythonを学ぶならVPSで ▼

AlmaLinuxが使える
「おすすめVPS」

VPSランキングを見る

Pythonスキルを活かす
「ITエンジニア転職」

転職エージェントを見る

コメント