クローリング 모니터링 자동화 — 데이터 품질을 24시간 유지하는 방법

クローリング 모니터링 자동화와 데이터 품질을 24시간 지키는 방법에 대한 안내. クローラが静かに壊れるパターンと自動回復戦略をお伝えします.

3,040
クローリング 모니터링 자동화 — 데이터 품질을 24시간 유지하는 방법
目次

クローリングモニタリングの自動化 — データ品質を24時間守る方法

クローラを作ることはプロジェクトの20%です。残りの80%は運用です。

"うまく動いていたクローラがある日突然空のデータを返し始めたが、誰も気づかなかった" — クローリングシステムを運用したことがある人なら一度は経験したことでしょう。この記事では、クローラが静かに壊れるパターンと、それを自動的に検出して修復する方法をまとめます。

目次

クローラが静かに壊れる5つのパターン

クローラの最も危険な失敗はエラーなしに間違ったデータを返すことです。HTTP 200が返ってきても、実際のデータは空であったり間違った値が入っていることがあります。

1. HTML構造の変更

対象サイトがリニューアルしたりA/Bテストを行うと、CSSセレクタが合わずデータの抽出に失敗します。エラーは出ないが結果はNoneまたは空の文字列です。

2. ボットブロックの強化

IPブロック、CAPTCHA、Cloudflare保護などが突然適用されます。応答コードは200ですが、返されるのは「アクセスが制限されました」といったブロックページです。

3. タイムアウト&ネットワークエラー

対象サーバの応答が遅くなったり、特定の時間帯に断続的に失敗します。再試行ロジックがないとデータが欠落します。

4. データスキーマの変更

価格フィールドがpriceからsalePriceに変わったり、日付形式が変更されます。クローラは正常に動作しますが、後続パイプライン(DBロード、分析など)で問題が発生します。

5. ページネーション/無限スクロールの変更

"次のページ"ボタンが消えたり、無限スクロールAPIエンドポイントが変更されます。最初のページだけ収集して終わる状況が生じます。

これら5つのパターンの共通点は何でしょうか? ログだけ見ると正常に見えるということです。

モニタリングすべき主要指標4つ

クローラが「正常のふり」を壊れるのを捉えるには、単純なエラーログではなくデータレベルのモニタリングが必要です。

1. 成功率(Success Rate)

単純なHTTP 200だけでなく、実際に有効なデータを返した割合を追跡します。

# 성공률 모니터링 예시
from datetime import datetime

def monitor_crawl_success(results):
    total = len(results)
    valid = sum(1 for r in results if r.get("title") and r.get("price"))
    success_rate = valid / total * 100 if total > 0 else 0

    # 성공률이 임계값 이하면 알림
    if success_rate < 90:
        send_alert(
            level="warning" if success_rate >= 70 else "critical",
            message=f"크롤링 성공률 저하: {success_rate:.1f}% ({valid}/{total})",
            timestamp=datetime.now().isoformat()
        )

    return {"success_rate": success_rate, "total": total, "valid": valid}

2. 応答時間(Response Time)

平均応答時間が突然2〜3倍に増加すると、ブロックが始まったり対象サーバに問題があるサインです。

3. データ完全性(Completeness)

必須フィールドがすべて埋まっているか確認します。"価格"フィールドがある結果の割合、"画像URL"がある割合などを追跡します。

def check_data_completeness(results, required_fields):
    """필수 필드 완전성 체크"""
    if not results:
        return {field: 0.0 for field in required_fields}

    completeness = {}
    for field in required_fields:
        filled = sum(1 for r in results if r.get(field))
        completeness[field] = filled / len(results) * 100

    # 특정 필드 완전성이 급격히 떨어지면 스키마 변경 의심
    for field, rate in completeness.items():
        if rate < 80:
            send_alert(
                level="warning",
                message=f"필드 '{field}' 완전성 {rate:.1f}%로 하락 — 스키마 변경 확인 필요"
            )

    return completeness

4. スキーマ変更の検知

収集データの構造を定期的に比較します。新しいフィールドが追加されたり、既存フィールドの値形式が変わると通知を送ります。

通知の自動化設定

モニタリング指標を監視していても、人がダッシュボードを24時間見ているわけにはいきません。通知の自動化は必須です。

import requests
import smtplib
from email.mime.text import MIMEText

def send_slack_alert(webhook_url, message, level="warning"):
    """Slack 웹훅으로 알림 전송"""
    emoji = "" if level == "warning" else ""
    payload = {
        "text": f"{emoji} *크롤링 모니터링 알림*\n{message}",
        "username": "Crawl Monitor",
    }
    requests.post(webhook_url, json=payload)

def send_email_alert(to_email, subject, body):
    """이메일 알림 전송"""
    msg = MIMEText(body)
    msg["Subject"] = f"[크롤링 알림] {subject}"
    msg["From"] = "monitor@your-domain.com"
    msg["To"] = to_email

    with smtplib.SMTP("smtp.gmail.com", 587) as server:
        server.starttls()
        server.login("your-email", "app-password")
        server.send_message(msg)

通知設定のヒント:
- 段階的通知: 成功率が90%未満 → Slack警告、70%未満 → メール + PagerDuty
- フラッピング防止: 3回連続失敗時のみ通知(一時的なエラーを無視)
- 通知疲れ管理: 同じ問題について1時間に最大1回の通知
- 復旧通知: 問題解決時に"正常復旧"通知も送り、安心させる

自動復旧戦略

通知だけでは不十分です。一般的な失敗パターンは自動的に復旧できます。

1. 指数バックオフ再試行(Exponential Backoff)

import time
import random

def crawl_with_retry(url, max_retries=3):
    """지수 백오프 재시도 — 일시적 오류 자동 복구"""
    for attempt in range(max_retries):
        try:
            result = crawl_page(url)
            if result and result.get("data"):
                return result
        except Exception:
            pass

        # 재시도 간격: 1초 → 2초 → 4초 (+ 랜덤 지터)
        wait = (2 ** attempt) + random.uniform(0, 1)
        time.sleep(wait)

    return None  # 재시도 모두 실패 → 알림으로 넘김

2. プロキシローテーション

IPブロックを検知した場合、自動的に他のプロキシに切り替えます。

def crawl_with_proxy_rotation(url, proxies):
    """프록시 로테이션 — IP 차단 시 자동 전환"""
    for proxy in proxies:
        try:
            response = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=10)
            if response.status_code == 200 and not is_block_page(response.text):
                return response
        except requests.RequestException:
            continue

    send_alert(level="critical", message=f"모든 프록시에서 {url} 차단됨")
    return None

3. フォールバック戦略

主要なクローリング方法が失敗した場合、代替経路に切り替えます。
- CSSセレクタが失敗 → XPathで試行
- APIエンドポイント変更 → モバイルバージョンページに切り替え
- 特定IP範囲ブロック → 別のリージョンのプロキシを使用

現実は? これらすべてを自分で構築し維持するにはかなりのエンジニアリングリソースが必要です。

直接運用 vs 管理型サービス — コスト比較

クローリングモニタリング/運用システムを直接構築するコストを率直に比較します。

項目 直接運用 管理型サービス(ハッシュスクレイパー)
初期構築 2〜4週間の開発時間 設定後すぐに開始
プロキシコスト 月額$100〜500+ 含まれている
モニタリング 直接構築が必要 組み込み
障害対応 開発者が直接 自動復旧 + 専任対応
サイト変更対応 手動更新 自動検知 + 修正
人件費 エンジニア時間(最大のコスト) サービス料金に含まれている

直接運用する際の最大のコストは見えないコストです。深夜にクローラが壊れて対応する時間、サイト構造の変更を把握しセレクタを修正する時間、プロキシを管理する時間。これらの時間が積み重なると製品開発に注ぐべきリソースが失われます。

ハッシュスクレイパーはこの運用負担を代わりに引き受けます。モニタリング、障害対応、サイト変更の追跡がサービスに組み込まれているため、開発チームはクローリングデータを活用することに集中できます。

まとめ

クローリングシステムは作る瞬間ではなく運用する毎日毎日が本当の戦いです。

モニタリングのないクローラは時限爆弾です。今うまく動くからといって明日もうまく動くという保証はありません。対象サイトは毎日変化し、ボットブロックはますます洗練されています。

直接モニタリングシステムを構築するか、管理型サービスを利用するか、重要なのは1つだけです: クローラが壊れたときにすぐに気づける構造を作ってください。

クローリング運用に疲れたら、ハッシュスクレイパーにお問い合わせください。モニタリングと保守が組み込まれた管理型クローリングサービスで、データ品質を24時間守ります。

コメント

コメントする

メールアドレスは公開されず、返信通知にのみ使用されます。

続けて読む

Get notified of new posts

We'll email you when 해시스크래퍼 기술 블로그 publishes new content.

Your email will only be used for new post notifications.