// 04 — log analysis
アクセスログ解析への応用
Apache / Nginx の Combined Log Format を例に、正規表現による各フィールド抽出パターンをまとめます。
Combined Log Format の構造
192.168.1.100 - - [03/May/2026:15:28:10 +0900] "GET /index.html HTTP/1.1" 200 4321 "-" "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36"
ログIPアドレス抽出
/^(\d{1,3}(?:\.\d{1,3}){3})/
行頭のIPv4アドレスをキャプチャ。グループ\1で取得できます。
ログリクエストURI抽出
/"(?:GET|POST|PUT|DELETE|HEAD)\s(\/[^\s"]*)/
HTTPメソッドに続くURIパス部分をキャプチャ。クエリ文字列も含む。
ログステータスコード抽出
/" (\d{3}) /
リクエスト行の直後に続く3桁のHTTPステータスコード。
ログUser-Agent抽出
/"([^"]+)"$/
行末のダブルクォート内文字列(User-Agent)をキャプチャ。
ログボットUA判定
/[Bb]ot|[Cc]rawler|[Ss]pider|[Ss]canner/
UA文字列にbot/crawler/spider/scannerを含む行をフィルタリング。
ログ静的ファイルを除外
/GET (?!.*\.(css|js|png|jpg|gif|ico|woff2?))/
否定先読みで静的アセットリクエストを除いたGETのみ抽出。
grep での活用例
# 404エラーのIPだけ抽出
grep ' 404 ' access.log | grep -oP '^[\d.]+' | sort | uniq -c | sort -rn
# ボットを除いたユニークIPカウント
grep -viP 'bot|crawler|spider' access.log | grep -oP '^[\d.]+' | sort -u | wc -l
# 特定URIへのアクセスを時間帯別に集計
grep -P 'GET /api/' access.log | grep -oP '\d{2}(?=:\d{2}:\d{2})' | sort | uniq -c
// 05 — python re module
Python re モジュールでの使い方
基本操作
import re
# match() — 文字列の先頭からマッチするか確認
m = re.match(r'^[0-9]+$', '12345')
if m:
print('数字のみ OK')
# search() — 文字列中のどこかにマッチするか確認
m = re.search(r'\d+', 'abc123def')
print(m.group()) # → '123'
# findall() — すべてのマッチをリストで取得
nums = re.findall(r'\d+', 'tel:03-1234-5678')
print(nums) # → ['03', '1234', '5678']
# sub() — マッチ箇所を置換
result = re.sub(r'[!-/:-@\[-`{-~]', '', 'Hello, World!')
print(result) # → 'Hello World' (記号を除去)
# compile() — 繰り返し使うパターンはコンパイルしてキャッシュ
pattern = re.compile(r'^[ぁ-ん]+$')
print(pattern.match('ひらがな')) # Match object
print(pattern.match('カタカナ')) # None
日本語文字除去(実践パターン)
import re
# 英数字・ひらがな・カタカナ・漢字以外をすべて除去
def clean_japanese(text):
pattern = re.compile(
r'[^0-9a-zA-Z0-9\u3041-\u3096\u30A1-\u30FA'
r'\u2E80-\u2FDF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF]'
)
return pattern.sub('', text)
print(clean_japanese('Hello! こんにちは◆World123'))
# → 'Helloこんにちは World123'
アクセスログのパース(まとめ)
import re
LOG_PATTERN = re.compile(
r'^(?P<ip>[\d.]+) .+? \[(?P<time>[^\]]+)\] '
r'"(?P<method>\w+) (?P<uri>[^\s"]+)[^"]*" '
r'(?P<status>\d{3}) (?P<size>\d+|-) "[^"]*" "(?P<ua>[^"]*)"'
)
with open('access.log') as f:
for line in f:
m = LOG_PATTERN.match(line)
if m:
d = m.groupdict()
# d['ip'], d['uri'], d['status'], d['ua'] で各フィールドにアクセス
if d['status'] == '404':
print(f"{d['ip']} → {d['uri']}")
// 06 — unicode ranges
日本語 Unicode レンジ一覧
日本語の文字をUnicodeコードポイントで正確に扱う場合のレンジ一覧です。[一-龥] のような範囲指定よりも厳密な処理が必要な場合に参照してください。
| 文字種 | Unicodeレンジ | 正規表現(Python) | 備考 |
| ひらがな | U+3041–U+3096 | \u3041-\u3096 | 小書き文字含む(ぁ〜ゖ) |
| カタカナ | U+30A1–U+30FA | \u30A1-\u30FA | ァ〜ヺ(小書き・長音符含む) |
| CJK部首補助 | U+2E80–U+2FDF | \u2E80-\u2FDF | 康熙部首含む |
| 漢字の踊り字 | U+3005, U+303B | \u3005\u303B | 々(繰り返し記号)〻 |
| 漢数字ゼロ | U+3007 | \u3007 | 〇 |
| CJK統合漢字拡張A | U+3400–U+4DBF | \u3400-\u4DBF | 希少漢字を含む |
| CJK統合漢字 | U+4E00–U+9FFF | \u4E00-\u9FFF | 一般的な漢字の大半 |
| CJK互換漢字 | U+F900–U+FAFF | \uF900-\uFAFF | 互換性のために収録 |
| CJK拡張B〜F等 | U+20000–U+2FFFF | [\uD840-\uD87F][\uDC00-\uDFFF] | サロゲートペア(JS等で注意) |
JavaScriptでサロゲートペアを含む漢字を扱う場合は、/u フラグ(Unicode モード)を使うと [\u{20000}-\u{2FFFF}] のように簡潔に書けます。
包括的な日本語チェック(Python)
# 英数字 + 日本語全文字種を許可する包括パターン
JP_FULL = re.compile(
r'[^0-9a-zA-Z0-9'
r'\u3041-\u3096' # ひらがな
r'\u30A1-\u30FA' # カタカナ
r'\u2E80-\u2FDF' # CJK部首補助
r'\u3005\u3007\u303B' # 踊り字・漢数字ゼロ
r'\u3400-\u4DBF' # CJK拡張A
r'\u4E00-\u9FFF' # CJK統合漢字
r'\uF900-\uFAFF]' # CJK互換
)