AI

Webスクレイピング比較:Scrapy vs Crawlee vs Playwright-Python でスクレイピングを実装する

オープンソースラボ編集部2026年6月14日

Webスクレイピング比較:Scrapy vs Crawlee vs Playwright-Python でスクレイピングを実装する

ECサイトの価格監視・競合分析・データ収集・SEO調査などWebスクレイピングはデータエンジニアリングの重要なスキルです。Scrapy(Python製・フル機能フレームワーク・Spider中心)・Crawlee(TypeScript製・Apify発・ブラウザ自動化統合)・Playwright-Python(Microsoft製・ヘッドレスブラウザ・動的サイト対応)の3つが2026年のOSSスクレイピングツール主要選択肢です。

OSSスクレイピングを使う理由

  • データ収集自動化: ECサイトの価格変動・ニュース・不動産情報を定期収集してDB化
  • 競合分析: 競合他社のWebサイトを定期クロールして製品情報・価格・コンテンツを追跡
  • SEO調査: クロールで内部リンク・メタデータ・構造化データを一括取得して分析
  • コスト削減: ScrapingBee($49/月〜)などのスクレイピングSaaSを使わずに自前で構築

主要ツールの概要

Scrapy

2008年公開、Python製のOSSです。GitHubスター52k+。Pythonのデファクトスタンダードなフル機能Webスクレイピングフレームワークで、Spider(クローラー)・Pipeline(データ処理)・Middleware(リクエスト/レスポンス処理)・Feed Exporters(CSV/JSON/DB出力)が統合されています。

# Scrapy: ECサイトの価格監視Spider
import scrapy
from dataclasses import dataclass
from typing import Generator

@dataclass
class ProductItem:
    name: str
    price: float
    sku: str
    in_stock: bool
    url: str

class EcPriceSpider(scrapy.Spider):
    name = 'ec_price_monitor'
    allowed_domains = ['shop.example.com']
    start_urls = ['https://shop.example.com/products']

    custom_settings = {
        'DOWNLOAD_DELAY': 1.5,         # 1.5秒間隔でリクエスト(サーバーに優しく)
        'RANDOMIZE_DOWNLOAD_DELAY': True,
        'CONCURRENT_REQUESTS': 4,
        'ROBOTSTXT_OBEY': True,        # robots.txtを尊重
        'USER_AGENT': 'Mozilla/5.0 (compatible; PriceBot/1.0)',
        'ITEM_PIPELINES': {
            'ec_spider.pipelines.PostgresPipeline': 300,
        },
        'HTTPCACHE_ENABLED': True,     # 開発時はキャッシュを有効化
    }

    def parse(self, response: scrapy.http.Response) -> Generator:
        '''商品一覧ページをパース→各商品詳細ページをFollowする'''
        for product_link in response.css('a.product-card::attr(href)').getall():
            yield response.follow(product_link, callback=self.parse_product)

        # ページネーション処理
        next_page = response.css('a.pagination__next::attr(href)').get()
        if next_page:
            yield response.follow(next_page, callback=self.parse)

    def parse_product(self, response: scrapy.http.Response) -> dict:
        '''商品詳細ページから価格・在庫情報を抽出'''
        price_text = response.css('[itemprop="price"]::attr(content)').get() or '0'
        yield {
            'name': response.css('h1.product-title::text').get('').strip(),
            'price': float(price_text),
            'sku': response.css('[itemprop="sku"]::text').get(''),
            'in_stock': bool(response.css('[itemprop="availability"][href*="InStock"]')),
            'url': response.url,
            'scraped_at': response.headers.get('Date', b'').decode(),
        }
# pipelines.py: ScrapyのItemをPostgreSQLに保存するPipeline
import psycopg2
from itemadapter import ItemAdapter

class PostgresPipeline:
    def open_spider(self, spider):
        self.conn = psycopg2.connect('postgresql://scraper:pass@localhost/prices')
        self.cursor = self.conn.cursor()
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS product_prices (
                id SERIAL PRIMARY KEY,
                name TEXT, price NUMERIC(10,2), sku TEXT,
                in_stock BOOLEAN, url TEXT, scraped_at TIMESTAMP DEFAULT NOW()
            )
        ''')

    def process_item(self, item, spider):
        self.cursor.execute(
            'INSERT INTO product_prices (name, price, sku, in_stock, url) VALUES (%s, %s, %s, %s, %s)',
            (item['name'], item['price'], item['sku'], item['in_stock'], item['url']),
        )
        self.conn.commit()
        return item

    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()

Crawlee

2022年公開(Apify)、TypeScript製のOSSです。GitHubスター16k+。Apify(商用スクレイピングプラットフォーム)が作ったOSSのWebスクレイピングライブラリで、Cheerio(高速HTML解析)・Playwright・Puppeteerをシームレスに切り替えながら使えます。自動セッション管理・プロキシローテーション・キューによるURL管理が統合されています。

// Crawlee: TypeScript/Node.jsでのスクレイピング(Playwright統合)
import { PlaywrightCrawler, Dataset } from 'crawlee';

const crawler = new PlaywrightCrawler({
  maxRequestsPerCrawl: 100,
  launchContext: {
    launchOptions: {
      headless: true,  // trueで非表示、falseでブラウザ表示(デバッグ用)
    },
  },
  // プロキシ設定(IPバン回避)
  proxyConfiguration: {
    proxyUrls: [
      'http://proxy1:8080',
      'http://proxy2:8080',
    ],
  },
  async requestHandler({ page, request, enqueueLinks }) {
    // JavaScriptレンダリング後の動的コンテンツを取得
    await page.waitForSelector('.product-list', { timeout: 10000 });

    const products = await page.$$eval('.product-card', (cards) =>
      cards.map((card) => ({
        name: card.querySelector('.product-name')?.textContent?.trim() ?? '',
        price: parseFloat(card.querySelector('.price')?.dataset.price ?? '0'),
        url: (card.querySelector('a') as HTMLAnchorElement)?.href ?? '',
      }))
    );

    await Dataset.pushData(products);  // JSONLファイルに自動保存

    // 次のページへのリンクをキューに追加
    await enqueueLinks({
      selector: 'a.pagination-next',
      label: 'LIST',
    });
  },
  failedRequestHandler({ request, error }) {
    console.error(`失敗: ${request.url} - ${error.message}`);
  },
});

await crawler.run(['https://shop.example.com/products']);
// 結果はデフォルトで./storage/datasets/default/に保存

Playwright-Python

2020年公開(Microsoft)、Python製のOSSです。GitHubスター70k+(本体)。Microsoftが開発したクロスブラウザ(Chromium・Firefox・WebKit)自動化ライブラリで、JavaScript実行・Ajax待機・フォーム操作・スクリーンショット・PDFエクスポートができます。動的SPAサイトのスクレイピングに最適です。

# Playwright-Python: SPA・JavaScriptレンダリングサイトをスクレイピング
import asyncio
from playwright.async_api import async_playwright, Page
import json

async def scrape_with_intercept(url: str) -> list:
    '''XHR/Fetch APIをインターセプトして内部APIのJSONレスポンスを取得'''
    api_responses = []

    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            viewport={'width': 1280, 'height': 720},
        )
        page = await context.new_page()

        # APIレスポンスをインターセプト(Ajax通信を傍受)
        async def handle_response(response):
            if '/api/products' in response.url and response.status == 200:
                try:
                    data = await response.json()
                    api_responses.append(data)
                except Exception:
                    pass

        page.on('response', handle_response)
        await page.goto(url, wait_until='networkidle')

        # 「もっと見る」ボタンを繰り返しクリックして全商品を取得
        while True:
            more_btn = await page.query_selector('button.load-more:not([disabled])')
            if not more_btn:
                break
            await more_btn.click()
            await page.wait_for_timeout(1500)

        await browser.close()
    return api_responses

async def scrape_table_data(url: str) -> list:
    '''テーブルデータを含むページをスクレイピング(React/Vue SPA対応)'''
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page: Page = await browser.new_page()
        await page.goto(url, wait_until='domcontentloaded')
        await page.wait_for_selector('table.data-table', timeout=10000)

        rows = await page.$$eval('table.data-table tbody tr', lambda rows: [
            [cell.innerText.strip() for cell in row.querySelectorAll('td')]
            for row in rows
        ])
        await browser.close()
        return rows

if __name__ == '__main__':
    results = asyncio.run(scrape_with_intercept('https://spa.example.com/products'))
    print(json.dumps(results, ensure_ascii=False, indent=2))

機能比較表

比較項目ScrapyCrawleePlaywright-Python
JavaScript対応△(Splash連携)
速度(静的HTML)✅ 最速
TypeScript対応
セッション管理手動実装
GitHub Stars52k+16k+70k+

スクレイピングツールはDevOpsカテゴリ/categories/devopsのデータパイプライン(dbt/Airbyte)と組み合わせてスクレイピング→PostgreSQL→dbt変換→BI分析のELTパイプラインを構築します。LLMツールカテゴリ/categories/llm-toolsのRAGフレームワーク(LlamaIndex/LangChain)とPlaywrightを組み合わせてWebページをスクレイピングしてベクトルDBに格納するナレッジベース自動更新パイプラインを実現します。

FAQ

Q. ScrapyでJavaScriptレンダリングが必要なSPAサイトをスクレイピングするには?

A. Scrapy-Playwright(scrapy-playwright)プラグインでScrapyにPlaywrightを統合してJSレンダリング対応にします。インストール: pip install scrapy-playwright playwright && playwright install chromium。Settings設定: DOWNLOAD_HANDLERS = {'https': 'scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler', 'http': 'scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler'}TWISTED_REACTOR = 'twisted.internet.asyncioreactor.AsyncioSelectorReactor'。Spider実装: yield scrapy.Request(url, meta={'playwright': True, 'playwright_include_page': True, 'playwright_page_methods': [PageMethod('wait_for_selector', '.products'), PageMethod('click', 'button.load-more')]})→Playwrightが動的コンテンツをレンダリング→通常のScrapyのparse関数でCSSセレクターを使って解析。

Q. Playwright-Pythonでボット検知を回避するステルス設定はどうすればいいですか?

A. Playwright-stealth(playwright-extra+stealth plugin)でヘッドレスブラウザの特徴を隠蔽します。インストール: pip install playwright-stealth。設定: from playwright_stealth import stealth_asyncasync with async_playwright() as p: browser = await p.chromium.launch(); page = await browser.new_page(); await stealth_async(page)。追加設定: await page.set_extra_http_headers({'Accept-Language': 'ja-JP,ja;q=0.9', 'Accept-Encoding': 'gzip, deflate, br'})await context.add_cookies([{'name': 'session', 'value': 'xxx', 'domain': '.example.com', 'path': '/'}])でCookieを事前設定。プロキシ: await p.chromium.launch(proxy={'server': 'http://proxy:8080', 'username': 'user', 'password': 'pass'})で住宅用プロキシ(Residential Proxy)を経由してIPバンを回避。CAPTCHAバイパス: 2captchaやCapSolver APIと連携してCAPTCHAを自動解決→Playwrightで入力フォームに解答を自動入力。

Q. CrawleeとScrapyのどちらを選ぶべきですか?

A. Python・静的HTML中心・大規模クロールならScrapyTypeScript/Node.js・動的SPAサイト・Playwright統合・チーム開発ならCrawleeが向いています。Scrapy優位: ①52kスターの最大コミュニティ→Middleware・Extensionが豊富②非同期HTTPリクエスト(Twisted)で静的サイトの大量クロールが最速③PipelineとItem Processorで複雑なデータ変換・検証をPythonで実装④Scrapy CloudやScrapydでのデプロイが容易。Crawlee優位: ①TypeScript製で型安全なコード③Playwright/Puppeteer/Cheerioをシームレスに切り替え→動的JSサイトも静的サイトも同一フレームワーク③自動プロキシローテーション・セッション管理→IPバン回避が組み込み済み④RequestQueueで大量URLのキュー管理が簡単⑤Dataset・KeyValueStoreで収集データを整理・保存するストレージ抽象化。

Q. ScrapyとPlaywrightを使ったスクレイピングは法的に問題ないですか?

A. スクレイピングの合法性はサイトのToS・robots.txt・目的・手法・データの使い方によって異なります。基本原則: ①ROBOTSTXT_OBEY = Trueでrobots.txtを尊重(Scrapyのデフォルト設定)②DOWNLOAD_DELAY = 2で適切な間隔でリクエスト(サーバーに負荷をかけない)③ToS(利用規約)を読んでスクレイピング禁止条項がないか確認④個人情報(名前・メールアドレス)の収集・保存はGDPR/個人情報保護法に注意⑤著作権のあるコンテンツをそのまま再配布することは著作権侵害の可能性。合法的なユースケース: 公開価格情報の収集・学術研究・自社サイトの監視・SEO分析。避けるべきこと: ログイン認証をバイパス・CAPTCHA解析・Rate Limitの意図的回避・競合を不正に妨害するための大量リクエスト。

まとめ

ユースケース推奨ツール
Python・静的HTML・大規模クロールScrapy
TypeScript・SPA・Playwright統合Crawlee
動的JS・API傍受・ブラウザ自動化Playwright-Python

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。