Contents
ものログとは何か、取得したい情報の概要
ものログは SaaS 型のアクセス・エラーログ可視化サービスで、Web アプリや API の利用状況をリアルタイムに把握できます。業務上は「日次/時間別アクセス数」「ステータスコード別エラー一覧」「ユーザーエージェント分布」などの指標が頻繁に求められます。本稿では 取得したいデータを先に定義し、公式 API と UI のどちらから情報を抽出すべきかを判断するフロー を示します。結論としては、HTML だけで完結できるケースは少なく、公式が提供している JSON API(認証が必要)を利用する方が安定です。
スクレイピング準備:環境構築とページ分析
このセクションでは実装前に必ず行うべき作業を解説します。環境が整っていないと、後のコードでエラーが頻発し、保守性も低下します。
Python 環境構築手順
Python 3.11 以上を前提に、仮想環境を作成して必要パッケージをインストールします。
|
1 2 3 4 5 6 7 8 9 10 11 |
# プロジェクトディレクトリの作成と移動 mkdir monolog-scrape && cd monolog-scrape # 仮想環境の作成 (venv) python -m venv .venv source .venv/bin/activate # Windows の場合は .venv\Scripts\activate # パッケージマネージャーを最新化し、必要ライブラリをインストール pip install --upgrade pip pip install requests beautifulsoup4 selenium pandas backoff python-dotenv |
requestsとbeautifulsoup4は静的ページ取得の基本。- 動的ページがある場合は
selenium、データ加工はpandasを使用します。 backoffはリトライロジックをシンプルに実装でき、python-dotenvは環境変数管理に便利です。
HTML 構造確認と必要要素
取得対象ページの構造を把握することがスクレイピング成功の鍵です。Chrome の DevTools(F12)で Elements タブを開き、以下をチェックします。
| 確認項目 | 具体的な見方 |
|---|---|
| テーブル形式か JSON API か | <table> 要素があるか、Network パネルで application/json のレスポンスが出ているか |
| 行・列の CSS セレクタ | 行は通常 <tr>、列は <td class="col-name"> 等。右クリック → Copy → Selector で取得可能 |
| ページ遷移やフィルタリング方式 | ボタンやドロップダウンが JavaScript で制御されている場合は Selenium が必要になることが多い |
ポイント:HTML に直接ログデータが埋め込まれていないケースでは、バックエンドが提供する API エンドポイントを探す方が安定です。公式ドキュメント(Monolog API Reference)でエンドポイントと認証方式を必ず確認してください。
基本的な取得方法:Requests と BeautifulSoup の実装例
この章では「静的 HTML」または「認証済み JSON API」からデータを取得する最小構成のコードを示します。すべての機密情報は環境変数で管理し、ハードコーディングを排除しています。
事前準備:.env ファイルと環境変数
|
1 2 3 4 |
# .env (プロジェクトルートに配置、git にコミットしないこと) MONOLOG_EMAIL=your@email.com MONOLOG_PASSWORD=SuperSecretPassword |
Python 側で python-dotenv を利用して読み込みます。
コードサンプルと解説
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
import os import time import requests from bs4 import BeautifulSoup import pandas as pd from dotenv import load_dotenv # .env の内容を環境変数へロード load_dotenv() # 環境変数から認証情報を取得(None が返ったら例外で停止) EMAIL = os.getenv("MONOLOG_EMAIL") PASSWORD = os.getenv("MONOLOG_PASSWORD") if not EMAIL or not PASSWORD: raise RuntimeError("環境変数 MONOLOG_EMAIL / MONOLOG_PASSWORD が設定されていません") # 1. セッション開始 → クッキー保持 session = requests.Session() # 2. ヘッダー偽装(User-Agent, Referer は最新ブラウザ文字列に合わせる) HEADERS = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36" ), "Referer": "https://app.monolog.io/login", "Content-Type": "application/json", } # 3. ログイン API(公式ドキュメントでエンドポイントとリクエスト形式を必ず確認) login_url = "https://app.monolog.io/api/auth/login" payload = {"email": EMAIL, "password": PASSWORD} resp = session.post(login_url, json=payload, headers=HEADERS) resp.raise_for_status() # HTTP エラーは例外で止める access_token = resp.json().get("accessToken") if not access_token: raise RuntimeError("アクセストークンが取得できませんでした") # Authorization ヘッダーを更新(トークンベース認証の場合) session.headers.update({"Authorization": f"Bearer {access_token}"}) # 4. ログ一覧 API の呼び出し例(エンドポイントは公式に合わせること) logs_api = "https://app.monolog.io/api/logs?limit=1000" log_resp = session.get(logs_api, headers=HEADERS) log_resp.raise_for_status() logs_json = log_resp.json() # 取得した JSON データ # 5. 必要な項目だけ抽出して DataFrame に変換 records = [ { "日時": item["timestamp"], "ステータスコード": item["statusCode"], "URL": item["requestUrl"], "UA": item["userAgent"], } for item in logs_json.get("data", []) ] df = pd.DataFrame.from_records(records) print(df.head()) |
主な改善点
| 項目 | 従来の問題点 | 改善後 |
|---|---|---|
| 認証情報 | ソースコードにベアラ文字列を直書きしていた | .env と os.getenv で外部管理し、Git 管理から除外 |
| エンドポイント | 実際の API と合致しているか未確認だった | コメントで「公式ドキュメントで必ず確認」と明示 |
| ヘッダー偽装 | 重複した記述が散在していた | HEADERS を一元管理し、必要に応じて session.headers.update で付加 |
リクエスト間隔のベストプラクティス
過度なリクエストはサービス側からブロックされる可能性があります。公式ドキュメントが推奨する最小インターバル が明示されていない場合、以下を目安にしてください。
|
1 2 3 |
# 例:1 リクエストごとに 2 秒待機(指数バックオフは backoff ライブラリで実装可) time.sleep(2) |
高度な取得シナリオ:Selenium を用いた実装とエラーハンドリング
JavaScript が生成するテーブルや無限スクロールがある場合、requests だけではデータ取得が困難です。ここでは Selenium の基本構成と例外処理を示します。
Selenium が必要になるケース
- AJAX によるページ遷移:ボタン操作でデータがロードされる UI
- 無限スクロール:ログ一覧がスクロール時に追加取得される
- CAPTCHA / reCAPTCHA:自動化がブロックされた場合は手動介入が必要
上記のいずれかに該当すれば、ヘッドレスブラウザで操作する方が安全です。
リトライロジックと例外処理(backoff デコレータ使用)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import backoff import pandas as pd from dotenv import load_dotenv load_dotenv() EMAIL = os.getenv("MONOLOG_EMAIL") PASSWORD = os.getenv("MONOLOG_PASSWORD") options = webdriver.ChromeOptions() options.add_argument("--headless") # バックグラウンドで実行 options.add_argument("--no-sandbox") driver = webdriver.Chrome(options=options) @backoff.on_exception( backoff.expo, (webdriver.common.exceptions.TimeoutException, webdriver.common.exceptions.WebDriverException), max_tries=5, jitter=None, ) def fetch_logs_via_browser(): driver.get("https://app.monolog.io/login") # ----- ログイン処理(要素の CSS セレクタは実際に確認) ----- WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.NAME, "email")) ).send_keys(EMAIL) driver.find_element(By.NAME, "password").send_keys(PASSWORD) driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click() # ログイン完了まで待機 WebDriverWait(driver, 15).until( EC.url_contains("/dashboard") ) # ---------- ログページへ遷移 ---------- driver.get("https://app.monolog.io/logs") # テーブルがロードされるまで明示的に待つ table = WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.CSS_SELECTOR, "table.log-table")) ) rows = [] for tr in table.find_elements(By.CSS_SELECTOR, "tbody > tr"): cols = [td.text.strip() for td in tr.find_elements(By.TAG_NAME, "td")] rows.append(cols) return rows try: raw_data = fetch_logs_via_browser() df = pd.DataFrame(raw_data, columns=["日時", "ステータスコード", "URL", "UA"]) print(df.head()) finally: driver.quit() |
重要ポイント
- 指数バックオフで一時的なタイムアウトやネットワーク障害に自動リトライ。
WebDriverWaitとexpected_conditionsによる 明示的待機 を必ず入れることで、ページ描画完了前の要素取得エラーを防止。- 例外が発生したら 必ず
driver.quit()してリソースリークを回避。
法的留意点とコンプライアンスチェック
スクレイピングで得たログは分析だけでなく、社内レポートや外部システムへの連携に利用できます。しかし、ものログのサービス利用規約・ロボット排除標準(robots.txt)を無視すると、契約違反や法的リスクが生じます。
公式利用規約の確認手順
- 最新ドキュメントへアクセス:
https://docs.monolog.io/terms(2024 年以降更新されたページ)。 - 「自動取得」「API の商用利用」など、該当項目を検索。
- 規約に記載がある 「大量取得は原則禁止」 や 「エクスポート機能の使用推奨」 という文言は必ず遵守する。
⚠️ 本稿で示した「1 リクエスト ≥10 秒」「1 日 10,000 件未満」などの数値は、公式に明記がある場合のみ適用 してください。実際のポリシーはサービス側の
robots.txtと利用規約を併せて確認することが必須です。
robots.txt の取得と解釈例
|
1 2 |
curl -s https://app.monolog.io/robots.txt |
| 記述例 | 意味 |
|---|---|
User-agent: *Disallow: /logs/ |
すべてのクローラに対して /logs/ 配下への自動取得を禁止 |
Allow: /api/ |
API エンドポイントは取得許可(ただし利用規約が別途必要) |
実務的アドバイス:Disallow がある場合は スクレイピングではなく公式エクスポート機能や有償 API ライセンスの取得 を検討してください。
コンプライアンスチェックリスト
| チェック項目 | 判定基準・実施方法 |
|---|---|
| 認証情報の保管 | 環境変数または Secret Manager(AWS Secrets Manager、Google Secret Manager 等)で暗号化保存 |
| 取得頻度 | 公式が示すレートリミットがあればそれに従う。無い場合は 1 リクエスト/2–3 秒 を目安にし、ログ取得のスケジュールは平日の業務時間外に設定 |
| robots.txt の遵守 | curl で取得した内容を CI パイプラインの最初のステップで自動検証 |
| データ再配布・商用利用 | ものログ側から明示的な許諾がある場合のみ第三者へ提供。無い場合は社内限定に留める |
| 法的リスクのレビュー | 情報セキュリティ部門や法務部と事前に取得目的・方法を共有し、必要なら利用規約改訂の同意書を作成 |
取得データの活用例と保存形式
取得したログは CSV/JSON として永続化し、BI ツールやモニタリング基盤へ取り込むことが一般的です。ここでは実務で頻繁に使われるパイプライン例を示します。
データ整形・ファイル出力(UTF‑8 / ISO8601)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 既に DataFrame df が作成済みと仮定 import pathlib output_dir = pathlib.Path("outputs") output_dir.mkdir(exist_ok=True) timestamp = pd.Timestamp.now().strftime("%Y%m%d_%H%M%S") csv_path = output_dir / f"monolog_logs_{timestamp}.csv" json_path = output_dir / f"monolog_logs_{timestamp}.json" # CSV(UTF-8、インデックスなし、ISO8601 日付)で保存 df.to_csv(csv_path, index=False, encoding="utf-8", date_format="%Y-%m-%dT%H:%M:%SZ") # JSON(行指向レコード形式)で保存 df.to_json(json_path, orient="records", force_ascii=False, date_format="iso") print(f"CSV: {csv_path}\nJSON: {json_path}") |
- エンコーディングは必ず UTF‑8 に統一し、文字化けを防止。
- 日時形式は ISO8601 が多くの BI ツール(Tableau、PowerBI、QuickSight)と互換性があります。
実務での活用シナリオ
| シナリオ | フロー概要 |
|---|---|
| 定期レポート作成 | GitHub Actions で毎日 00:00 にスクリプトを実行、前日のログ CSV を生成し Slack の Webhook へ通知。 |
| 異常検知パイプライン | Lambda 関数が S3 に保存された CSV を読み込み、ステータスコード別件数を算出。エラーレートが閾値(例:5 %)を超えたら CloudWatch アラームを発火。 |
| ダッシュボード連携 | Amazon QuickSight が S3 の CSV/JSON をデータセットとしてインポートし、リアルタイムに近い可視化ダッシュボードを提供。取得は 1 時間ごとに再実行して更新。 |
まとめ
- まずは取得したい項目を明確化し、公式 API が存在すればそちらを優先する。
- 環境構築では仮想環境・
.envによる機密情報管理を徹底し、ハードコーディングを排除する。 requestsとBeautifulSoupは静的ページ・API 取得に、Seleniumは動的コンテンツ取得に使い分け、指数バックオフと明示的待機で堅牢化する。- 法的リスクは 公式利用規約・robots.txt の確認 → 取得頻度の制御 → 秘密情報の安全な保管 という三層防御で低減できる。
- 最後に、取得データは UTF‑8/ISO8601 に統一し、社内レポートや外部 BI ツールへシームレスに連携させれば、ものログから得られるインサイトを最大限活用できます。
本ガイドは執筆時点(2024 年)で確認できた情報に基づいています。実装前に必ず公式ドキュメントと利用規約の最新版をご確認ください。