🎯 カスタマイズ可能で検出回避型のクラウドブラウザ。自社開発のChromiumを搭載し、ウェブクローラーAIエージェント向けに設計されています。👉今すぐ試す
ブログに戻ります

ウェブクローラーの一般的な落とし穴とその解決策(コード例付き)

Michael Lee
Michael Lee

Expert Network Defense Engineer

16-Sep-2025

ウェブクローラーはHTTPリクエストを送信するだけではなく、JavaScriptのレンダリング、ボット対策、スケーラビリティ、エラーハンドリングに対処しなければなりません。この記事では、クローラーを構築する際に開発者が直面する一般的な落とし穴を見て、コードスニペットを使った実践的な解決策を提供します。


1. Robots.txtおよびクローリングポリシーの無視

クローラーがrobots.txtを無視すると、法的問題やIPブロックのリスクがあります。

悪い例:

python Copy
import requests

html = requests.get("https://example.com").text
# robots.txtのチェックなし

改善されたアプローチ:

python Copy
import urllib.robotparser

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

if rp.can_fetch("*", "https://example.com/page"):
    print("クローリングが許可されました")
else:
    print("robots.txtで禁止されています")

✅ 常にクローリングポリシーを尊重し、レート制限を実装しましょう。


2. 貪欲すぎるクローリング

1秒間に何千ものリクエストを送るのは、すぐに禁止される早い方法です。

解決策:

  • 遅延を追加する
  • 効率のために非同期クローリングを使用する
python Copy
import asyncio, aiohttp, random

async def fetch(session, url):
    async with session.get(url) as resp:
        return await resp.text()

async def main():
    urls = ["https://example.com/page1", "https://example.com/page2"]
    async with aiohttp.ClientSession() as session:
        for url in urls:
            html = await fetch(session, url)
            print(len(html))
            await asyncio.sleep(random.uniform(1, 3))  # 丁寧な遅延

asyncio.run(main())

3. JavaScriptレンダリングコンテンツの処理

静的クローラーはJSが重いページ(React、Vue、Angular)を見逃します。

解決策: ヘッドレスブラウザを使用する(例: Playwright、Puppeteer)。

python Copy
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://quotes.toscrape.com/js/")
    print(page.content())  # 現在JSレンダリングコンテンツを含む
    browser.close()

4. 非効率的なデータ抽出

壊れやすいセレクタをハードコーディングすると、クローラーが破損します。

BeautifulSoup + フォールバックを使用した改善されたアプローチ:

python Copy
from bs4 import BeautifulSoup

html = "<div><h1 class='title'>こんにちは</h1></div>"
soup = BeautifulSoup(html, "lxml")

# プライマリセレクタ
title = soup.select_one("h1.title")

# フォールバック
if not title:
    title = soup.find("h1")

print(title.text)

5. 重複コンテンツの収集

/page?id=123&session=abcのようなURLは重複を引き起こす可能性があります。

解決策: URLの正規化

python Copy
from urllib.parse import urlparse, urlunparse

def normalize(url):
    parsed = urlparse(url)
    clean = parsed._replace(query="")
    return urlunparse(clean)

print(normalize("https://example.com/page?id=1&session=xyz"))
# -> https://example.com/page

6. IPブロックとボット対策メカニズム

ウェブサイトはレート異常、フィンガープリンティング、およびCAPTCHAでボットを検出します。

Scrapyによる基本的なローテーション:

python Copy
class RotateUserAgentMiddleware:
    user_agents = [
        "Mozilla/5.0 ...",
        "Chrome/91.0 ...",
        "Safari/537.36 ..."
    ]

    def process_request(self, request, spider):
        import random
        request.headers['User-Agent'] = random.choice(self.user_agents)

解決策スタック:

  • プロキシとユーザーエージェントのローテーション
  • 住宅用/モバイルプロキシの使用
  • 必要に応じてCAPTCHAソルバーを統合

7. エラーハンドリング

ネットワークエラーは避けられません。再試行がなければ、クローラーは静かに失敗します。

再試行の例:

python Copy
import requests, time

def fetch(url, retries=3):
    for i in range(retries):
        try:
            return requests.get(url, timeout=5)
        except requests.exceptions.RequestException as e:
            print(f"エラー: {e}, 再試行 {i+1}")
            time.sleep(2**i)
    return None

8. スケーラビリティの課題

1,000ページに対して動作するクローラーは、10Mページでは失敗するかもしれません。

Scrapy + Redisによる分散クローリングの例:

bash Copy
scrapy runspider crawler.py -s JOBDIR=crawls/job1

使用するもの:

  • 分散タスクキュー用のRedis/Kafka
  • スケーリングのためのScrapy Cluster / Nutch
  • クローリング結果のためのクラウドストレージ

9. データ品質の問題

クローリングしたデータには重複、空のフィールド、または無効な形式が含まれる可能性があります。

解決策: スキーマ検証

python Copy
from pydantic import BaseModel, ValidationError

class Product(BaseModel):
    name: str
    price: float

try:
    item = Product(name="ラップトップ", price="数字ではない")
except ValidationError as e:
    print(e)

10. セキュリティとコンプライアンス

クローラーは個人情報または制限データのスクレイピングを避ける必要があります。
ユーザーデータを保存する前に、必ずGDPR/CCPAのコンプライアンスを確認してください。


結論

堅牢なクローラーを構築するには、技術的な精度と倫理的な責任が必要です。貪欲なクローリング、JavaScriptレンダリング、ボット対策、防御、スケーラビリティなどの落とし穴に対処することで、開発者は次のようなクローラーを設計できます:

  • 効率的 (最適化されたリソース使用)
  • 回復力がある (エラー耐性)
  • 準拠している (法的および倫理的)

Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。

最も人気のある記事

カタログ