【合法スクレイピング】robots.txt・著作権法第30条の4・負荷制御・TTLキャッシュの設計基準 アイキャッチ

Icons: Lobe Icons(MIT)

用語・仕組み
公開: 2026.09.02読了目安 8分

【合法スクレイピング】robots.txt・著作権法第30条の4・負荷制御・TTLキャッシュの設計基準

Webクローリング・データ収集を行うエンジニアが知っておくべき法規制、利用規約の遵守、サーバー負荷をかけないレート制御とTTLキャッシュ設計を解説します。

はじめに:安全で持続可能なデータ収集の原則

Webスクレイピングは、データ分析やAI学習データの収集において極めて強力な手段ですが、一歩間違えるとサーバー攻撃(DoS疑い)や利用規約違反、著作権侵害のトラブルに直面します。

日本の法規制(著作権法・不正アクセス禁止法・民法)に準拠しつつ、対象サーバーに負荷をかけない倫理的で安全なクローラー設計の標準仕様を解説します。


1. 日本におけるスクレイピング関連法規の全体像

法律・規約 主な論点 遵守すべき要件
著作権法第30条の4 AI学習や情報解析目的のデータ収集 思想・感情の享受を目的としない限り、原則として許諾なく複製可能。
刑法(偽計業務妨害罪) サーバーへの過度なアクセス負荷 秒間大量リクエストによるサーバーダウンの防止(レート制限の徹底)。
不正アクセス禁止法 認証防御の突破・セッション偽装 ログイン壁の不正突破や脆弱性攻撃の禁止。公開Webページのみを対象とする。
サイト利用規約 (ToS) スクレイピング禁止条項の有無 規約同意(ログイン等)を伴うサービスでは規約が契約として成立するため遵守必須。

2. 負荷をかけないクローラーの4大技術基準

  1. robots.txt の完全解釈と遵守:
    • Disallow ディレクティブおよび Crawl-delay の指定を必ずパーサーで検証し遵守する。
  2. 適切な User-Agent の明記:
    • ボット名、運営者URL、問い合わせメールアドレスをヘッダーに含める(例: MyBot/1.0 (+https://example.com/bot; contact@example.com))。
  3. リクエスト間隔の制御(Rate Limiting):
    • 同一ドメインへのアクセスは最低 1.0秒〜3.0秒の間隔を空ける。同時並列接続数はドメインあたり 1〜2 に制限。
  4. TTL(Time-To-Live)キャッシュによる無駄な再アクセスの排除:
    • ETag / Last-Modified ヘッダーを活用し、更新のないページは 304 Not Modified でスキップする。

3. Pythonによる安全なクローラー実装例

import time
import urllib.robotparser
import requests
from urllib.parse import urlparse

class EthicalCrawler:
    def __init__(self, base_url, user_agent="CDNTBot/1.0 (+https://cd-nt.com/bot)"):
        self.base_url = base_url
        self.user_agent = user_agent
        self.rp = urllib.robotparser.RobotFileParser()
        self.rp.set_url(f"{base_url}/robots.txt")
        try:
            self.rp.read()
        except Exception:
            pass
        self.last_request_time = 0
        self.min_interval = 1.5 # 最低1.5秒待機

    def can_fetch(self, url):
        return self.rp.can_fetch(self.user_agent, url)

    def fetch(self, url):
        if not self.can_fetch(url):
            print(f"Blocked by robots.txt: {url}")
            return None

        # レート制限待機
        elapsed = time.time() - self.last_request_time
        if elapsed < self.min_interval:
            time.sleep(self.min_interval - elapsed)

        headers = {"User-Agent": self.user_agent}
        resp = requests.get(url, headers=headers, timeout=10)
        self.last_request_time = time.time()
        return resp

法務と技術の双方を正しく理解し、節度ある運用を行うことが、長期的なデータインフラ構築の基盤となります。