はじめに
こんにちは。今回は、「独学エンジニア」サイトの学習の一環で作成したWikipediaアクセスログ解析CLIツールについてご紹介します。
このプロジェクトでは、PHP・MySQL・Dockerを使って、SQLによるデータの保存・検索・集計処理を実践的に学びました。
本記事はその学習の備忘録としてまとめたものです。
プロジェクトの概要
このCLIツールは、Wikipediaのアクセスログを読み込み、以下の解析を行います
- アクセス数の多い記事を上位から表示
- 特定の言語ドメイン(例:en, ja, deなど)の合計アクセス数を表示
ターミナル上から簡単に使えるようになっており、実際のログデータ(.gz
形式)をMySQLに取り込み、PHPからクエリで集計・表示する構成になっています。
GitHubリポジトリ:
https://github.com/zusa-uehara/wikipedia-log-analyzer
Wikipediaのログデータについて
本ツールで扱うWikipediaのログは、Wikimediaが提供しているページビュー統計データを使用しています。
このデータには、言語コード・記事タイトル・アクセス数などが含まれており、1時間ごとに記録された大規模なアクセスログが .gz
形式で配布されています。
設計とディレクトリ構成
以下のような設計と構成です。
- データ層:MySQL 8.0(Docker上に構築)
- アプリ層:PHP(主にCLIで実行)
- 環境:Docker ComposeでPHP+MySQL+DevContainerを一括構築
ディレクトリ構成
.
├── data/ # Wikipediaログファイル(.gz)
├── db/ # 初期SQL(テーブル作成)
├── src/ # PHPソースコード
├── .env # DB接続情報(Docker用)
├── docker-compose.yml # Dockerサービス定義
├── Dockerfile # PHPコンテナ設定
└── README.md
開発で意識したこと
SQLとPHPの連携
-
PDO
を使用するという課題だったので、PDOを使用しPHPから安全にSQLを実行できるようにしました。
ログの読み込みと整形処理
- 圧縮されたWikipediaのログファイル(.gz形式)をPHPで開いて、1行ずつ読み取るようにしました。
- 読み取ったデータをまとめて一度にデータベース(MySQL)に登録する方法を採用しました。
実装コマンドの例
-
php src/top_articles.php 10
→ 上位10記事を表示 -
php src/domain_summary.php ja en de
→ 言語ごとの合計アクセス表示
難しかった点と学び
DockerとMySQLの接続設定
- docker-compose.ymlでPHPコンテナとMySQLコンテナを連携させる設定に苦戦しました。
- 特に、PHPコンテナは起動しているのに、MySQLにうまく接続できず、アプリケーションが動かないことがありました。
- 接続エラーの原因がMySQLの起動タイミングやサービス名の指定ミスだったこともあり、MySQLを常に起動状態に保つようにしたり、depends_onで起動順序を調整したりして対応しました。
大きなデータの取り扱い
- Wikipediaのログファイルは1つで数百MBあり、メモリ消費や処理速度の課題がありました。
- いきなり大量のデータを扱うのではなく、まずは小さなサンプルデータを作成してテストを重ねながらコードを作成しました。
PDOの理解
- PHPのPDOを使ったデータベース操作は公式ドキュメントを読みましたが理解が難しく、
他の情報源も調べながら少しずつ使い方を習得しました。
コーディングスタイルの統一(PHP_CodeSniffer)
- PHPのコードはコーディング規約に則って書くという課題だったのでPSR-12に準拠するために
phpcs
を使いましたが、初回実行時に大量のエラーが表示され、正直かなり戸惑いました。 - インデントや空行の位置、関数の書き方など細かい指摘が多く、修正に時間がかかりました。
- 途中からは
phpcbf
を使って自動修正もしながら、少しずつルールに慣れていきました。
最後に
このプロジェクトは、「データを扱うアプリケーション」の構造や実装の流れを実践的に体験できる貴重な機会となりました。
PHPの基本構文から、SQLの集計ロジック、Dockerでの環境構築まで、一通りの流れを学べました。
まだまだ改善の余地はありますが、実際に動くものを作りながら学ぶことで理解が深まりました。
ご意見などあれば、ご連絡いただけらば幸いです。
最後まで読んでいただき、ありがとうございました。