0Pricing
AI Agents · レッスン

適切なスクレイピングの実践

robots.txtの遵守、User-Agentヘッダー、リクエスト間隔、キャッシュを学びます。

「適切なスクレイピングの実践」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。

節度あるスクレイピングが重要な理由

Webスクレイピングはサーバーに負荷をかけたり、利用規約に違反したり、エージェントのIPアドレスをアクセス禁止にされたりする可能性があります。責任あるスクレイピングでは、レート制限を守り、自分の身元を明らかにし、Webサイトが公開しているルールに従います。

このレッスンでは、倫理的かつ持続可能なスクレイピングのためのツールと手法を学びます。

robots.txtを確認する

すべてのWebサイトでは、robots.txtファイルを公開して、自動化されたエージェントがアクセスしてよいパス、またはアクセスしてはいけないパスを指定できます。Pythonの標準ライブラリには、このファイルを解析するurllib.robotparserが含まれています。

サイトをスクレイピングする前に、必ずrobots.txtを確認してください。

import urllib.robotparser

rp = urllib.robotparser.RobotFileParser()
rp.set_url('https://example.com/robots.txt')
rp.read()

# Check if our bot can fetch a specific path
can_fetch = rp.can_fetch('MyAgent/1.0', 'https://example.com/public-data')
print(f'Can fetch: {can_fetch}')  # True or False

cannot_fetch = rp.can_fetch('*', 'https://example.com/private/admin')
print(f'Admin allowed: {cannot_fetch}')  # Often False

説明的なUser-Agentを設定する

User-Agent HTTPヘッダーは、リクエストを行っている主体を識別します。正直なUser-Agentを設定すると、サイト管理者はボットの正体や、問題が発生した場合の連絡先を把握できます。ブロックを回避するためにブラウザになりすますことは、倫理的な懸念を招きます。

import httpx

headers = {
    # Honest, descriptive User-Agent
    'User-Agent': 'MyResearchBot/1.0 (contact: me@example.com; purpose: academic research)'
}

response = httpx.get(
    'https://example.com/data',
    headers=headers,
    timeout=10.0
)

print(response.status_code)

time.sleep()でレート制限を行う

1秒間に数百件のリクエストを送ると、サーバーに過大な負荷をかけ、サービス拒否攻撃とみなされることがあります。time.sleep()を使って、リクエストの間に遅延を追加してください。random.uniform()を使うと、遅延が機械的ではなく、より人間らしいものになります。

import time
import random
import httpx

urls = [
    'https://example.com/page/1',
    'https://example.com/page/2',
    'https://example.com/page/3'
]

for url in urls:
    response = httpx.get(url, timeout=10.0)
    print(f'Fetched {url}: {response.status_code}')

    # Wait between 1 and 3 seconds before the next request
    delay = random.uniform(1, 3)
    print(f'Sleeping {delay:.1f}s...')
    time.sleep(delay)

Retry-Afterヘッダーを尊重する

サーバーが429 Too Many Requestsを返す場合、多くの場合、何秒待つべきかを指定するRetry-Afterヘッダーが含まれています。エージェントはこの値を読み取り、すぐに再試行するのではなく、指定された時間を守って待機してください。

import time
import httpx

def fetch_with_retry(url: str) -> httpx.Response:
    while True:
        response = httpx.get(url, timeout=10.0)

        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 5))
            print(f'Rate limited. Waiting {retry_after}s...')
            time.sleep(retry_after)
            continue  # retry

        response.raise_for_status()
        return response

レスポンスをキャッシュして再取得を避ける

requests-cacheはHTTPレスポンスを自動的にディスクへキャッシュします。エージェントが同じURLを複数回取得する必要がある場合(開発中や再実行時など)、キャッシュされたレスポンスがサーバーにアクセスせず、すぐに返されます。

# pip install requests-cache
import requests_cache

# Install the cache globally — cached responses expire after 1 hour
requests_cache.install_cache(
    'agent_cache',
    backend='sqlite',
    expire_after=3600  # seconds
)

import requests

# First call: fetches from network and caches
response = requests.get('https://api.example.com/data')
print(response.from_cache)  # False

# Second call: returns cached result instantly
response2 = requests.get('https://api.example.com/data')
print(response2.from_cache)  # True

httpxでファイルベースのキャッシュを手動実装する

requests-cacheを使いたくない場合は、シンプルなファイルベースのキャッシュが便利です。レスポンスをURLのハッシュをキーとするJSONファイルとして保存し、ファイルが十分に新しければそこから再読み込みします。

import hashlib
import json
import os
import time
import httpx

CACHE_DIR = '/tmp/agent_cache'
os.makedirs(CACHE_DIR, exist_ok=True)

def cached_get(url: str, ttl_seconds: int = 3600) -> dict:
    key = hashlib.md5(url.encode()).hexdigest()
    cache_file = os.path.join(CACHE_DIR, key + '.json')

    if os.path.exists(cache_file):
        age = time.time() - os.path.getmtime(cache_file)
        if age < ttl_seconds:
            with open(cache_file) as f:
                return json.load(f)

    response = httpx.get(url, timeout=10.0)
    response.raise_for_status()
    data = response.json()
    with open(cache_file, 'w') as f:
        json.dump(data, f)
    return data

利用規約を読む

サイトをスクレイピングする前に、その利用規約を読んでください。自動アクセスやデータの商用利用を明確に禁止しているサイトも多くあります。ToSに違反すると、IPアドレスを禁止されるだけでなく、法的措置を受ける可能性があります。

公式APIが存在する場合は、HTMLのスクレイピングよりも必ずそちらを優先してください。公式APIのほうが高速で安定しており、法的な安全性も高くなります。

エラー発生時の指数バックオフ

リクエストが失敗したときは、すぐに再試行しないでください。指数バックオフを使用し、1秒、次に2秒、その次に4秒というように待機します。これにより、問題を抱えているサーバーへの過剰なリクエストを避けられます。これは本番環境のエージェントで使われる、実績のある方法です。

import time
import httpx

def fetch_with_backoff(url: str, max_retries: int = 4) -> dict:
    for attempt in range(max_retries):
        try:
            response = httpx.get(url, timeout=10.0)
            response.raise_for_status()
            return response.json()
        except (httpx.HTTPStatusError, httpx.RequestError) as e:
            if attempt == max_retries - 1:
                raise
            wait = 2 ** attempt  # 1, 2, 4, 8 seconds
            print(f'Attempt {attempt+1} failed: {e}. Retrying in {wait}s...')
            time.sleep(wait)
    return {}

必要なデータだけをスクレイピングする

エージェントが実際に必要とするデータだけを取得して、サーバーの負荷を最小限に抑えてください。小さなAPIエンドポイントで同じデータを取得できる場合は、ページ全体をダウンロードしないでください。完全な本文を取得する前に、HEADリクエストを使ってリソースが変更されているか確認します。

import httpx

def has_page_changed(url: str, last_etag: str = None) -> bool:
    headers = {}
    if last_etag:
        headers['If-None-Match'] = last_etag

    response = httpx.head(url, headers=headers, timeout=5.0)

    if response.status_code == 304:  # Not Modified
        return False

    new_etag = response.headers.get('ETag')
    print(f'New ETag: {new_etag}')
    return True

節度あるスクレイピングのルールまとめ

エージェントでサイトをスクレイピングする前に確認する、簡単なチェックリストです。

  • robots.txtを確認し、アクセス禁止のルールを守る
  • 正直で説明的なUser-Agentを設定する
  • リクエストの間にランダムな遅延を追加する(time.sleep(random.uniform(1,3)))
  • 429レスポンスのRetry-Afterヘッダーに従う
  • 重複した取得を避けるため、レスポンスをキャッシュする
  • サイトの利用規約を読む
  • 利用できる場合は、HTMLのスクレイピングより公式APIを優先する

理解度チェック:節度あるスクレイピング

倫理的で節度あるスクレイピングの実践についての理解度を確認しましょう。

振り返り:節度あるスクレイピングの実践

これで、責任を持ってスクレイピングを行うためのツール一式がそろいました。

  • アクセスが許可されている対象を確認するrobotparser
  • ボットの身元を明らかにする、説明的なUser-Agentヘッダー
  • リクエスト間で使用するtime.sleep(random.uniform(1,3))
  • 重複した取得を避けるrequests-cacheまたは手動キャッシュ
  • エラー処理のための指数バックオフ
  • 法的な意識:必ずToSを確認する

責任あるスクレイピングはより健全なWeb環境を築き、アクセス禁止を受けることなくエージェントを稼働させ続けるのに役立ちます。

よくある質問

「適切なスクレイピングの実践」レッスンは無料ですか?

はい。「適切なスクレイピングの実践」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。

「適切なスクレイピングの実践」で何を学びますか?

robots.txtの遵守、User-Agentヘッダー、リクエスト間隔、キャッシュを学びます。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Agentsを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「適切なスクレイピングの実践」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Agentsレッスンでコードを書いて実行できますか?

はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. エージェント向けHTTPクライアント:httpxとrequests
  2. BeautifulSoupによるHTML解析
  3. ページネーションと動的コンテンツの処理
  4. 適切なスクレイピングの実践
← AI Agentsに戻る