Crawlee-Python: 強力なWebスクレイピングおよびブラウザ自動化ライブラリ

この記事は、Python向けの新しいオープンソースのWebスクレイピングおよびブラウザ自動化ライブラリ、Crawleeのローンチを発表しています。JavaScriptバージョンの人気機能をPythonコミュニティにもたらします。

Anakin AIを無料で利用開始

Crawlee-Python: 強力なWebスクレイピングおよびブラウザ自動化ライブラリ

Start for free
目次

以下のHTMLコードを日本語に翻訳してください。 以下のURLが変換されることを確認してください: https://anakin.ai/apps/keyword または https://anakin.ai/blog/keyword 変換先は次の通りです: https://anakin.ai/ja-jp/apps/keyword https://anakin.ai/ja-jp/blog/keyword 以下がHTMLです:

Crawlee-Pythonは、信頼性の高い効率的なスクレイピングとブラウザ自動化のライブラリであり、開発者が信頼性のある効率的なスクレイパーを構築するのをサポートするために設計されています。オープンソースプロジェクトであるCrawlee-Pythonは、ウェブサイトのクロール、データの抽出、およびスケールでのウェブスクレイピングの複雑さを管理するための包括的なツールと機能を提供します。

💡
コードなしで独自のAgentic AIワークフローを作成したい場合は?

Anakin AIを使用すると、オンラインでビジュアルUIでAIワークフローを構築するパワーが得られます。GPT-4、Claude 3.5 Sonnet、Uncensored Dolphine Models、Stable Diffusion、DALLEなどの力を1つのワークフローに組み合わせることができます!

複雑なコーディングを忘れて、Anakin AIで日々の作業を自動化しましょう!
Anakin AIで簡単にAIエージェントワークフローを構築する
Anakin AIで簡単にAIエージェントワークフローを構築する

Crawlee-Pythonの主な機能

Crawlee-Pythonは、次のようなユニークな機能の組み合わせにより、他のウェブスクレイピングライブラリとは一線を画しています:

統一されたインターフェース:CrawleeはHTTPとヘッドレスブラウザのクロールのために一貫したインターフェースを提供し、開発者が簡単にメソッドを切り替えることができるようにします。

自動並列クローリング:ライブラリは、利用可能なシステムリソースに基づいて自動的にクローリング操作をスケーリングすることで、リソースの利用を最適化します。

型ヒント:Pythonで記述されたCrawleeは、完全な型ヒントのサポートを備えており、IDEの自動補完の改善とバグの早期検出を通じて開発者のエクスペリエンスを向上させます。

自動リトライ:ウェブサイトによってブロックされた場合にエラーを処理し、リクエストのリトライを自動的に行うための組み込みのメカニズムがあります。

プロキシのローテーションとセッション管理:スクレイピングの信頼性を高めるためのプロキシとセッションの管理ツールが統合されています。

設定可能なリクエストルーティング:効率的なデータ抽出のために、簡単にURLを適切なハンドラに指示することができます。

永続キュー:クロールするURLを管理するための堅牢なキューシステムがあります。

プラグインストレージ:タブularデータとファイルの両方を保存するための柔軟なオプションがあります。

ヘッドレスブラウザのサポート:Playwrightを使用してヘッドレスブラウザのクローリングをすぐにサポートします。

Asyncioベース:効率的な非同期操作のためにPythonの標準的なAsyncioライブラリに基づいて構築されています。

Crawlee-Pythonのはじめ方
Crawlee-Pythonのはじめ方

Crawlee-Pythonの使い方

Crawlee-Pythonを設定して使用するプロセスを見ていきましょう。

インストール

Crawlee-Pythonをはじめるには、Python 3.9以上が必要です。Crawleeをインストールする最も簡単な方法は、pipを使用することです:

pip install crawlee

追加の機能を利用するために、オプションの追加をインストールすることもできます:

pip install 'crawlee[beautifulsoup]'  # BeautifulSoupCrawler用
pip install 'crawlee[playwright]'     # PlaywrightCrawler用

PlaywrightCrawlerを使用する場合は、Playwrightの依存関係もインストールするのを忘れないでください:

playwright install

最初のクローラーの作成

PlaywrightCrawlerを使用して、ウェブページのタイトルとコンテンツをスクレイプするシンプルなクローラーを作成しましょう。

import asyncio
from crawlee import PlaywrightCrawler, PlaywrightCrawlingContext

async def main():
    crawler = PlaywrightCrawler(
        max_requests_per_crawl=50,  # ページ数を50に制限
    )

    @crawler.router.default_handler
    async def request_handler(context: PlaywrightCrawlingContext):
        data = {
            'url': context.page.url,
            'title': await context.page.title(),
            'content': (await context.page.content())[:1000]  # 最初の1000文字
        }
        await context.push_data(data)

    await crawler.run(['https://example.com'])
    
    # データをCSVにエクスポート
    await crawler.export_data('./result.csv')

if __name__ == '__main__':
    asyncio.run(main())

このスクリプトは以下の処理を行います:

  1. 50ページまでの制限を持つPlaywrightCrawlerインスタンスを作成します。
  2. ページのURL、タイトル、最初の1000文字のコンテンツを抽出するリクエストハンドラを定義します。
  3. 'https://example.com'からクローラーを実行します。
  4. 収集したデータをCSVファイルにエクスポートします。

高度な使用法:複数のURLをクロールする

クローラーを拡張して複数の起点URLを処理し、より高度な機能を実装しましょう。

import asyncio
from crawlee import PlaywrightCrawler, PlaywrightCrawlingContext

async def main():
    crawler = PlaywrightCrawler(
        max_requests_per_crawl=100,
        headless=True,
        browser_type='chromium'
    )

    @crawler.router.default_handler
    async def request_handler(context: PlaywrightCrawlingContext):
        page = context.page
        url = page.url

        # タイトルとメインコンテンツを抽出
        title = await page.title()
        content = await page.evaluate('() => document.body.innerText')

        # ページ上のすべてのリンクを抽出
        links = await page.evaluate('() => Array.from(document.links).map(link => link.href)')

        # データを保存
        await context.push_data({
            'url': url,
            'title': title,
            'content': content[:500],  # 最初の500文字
            'links_found': links
        })

        # クロール対象のリンクを追加
        await context.enqueue_links()

    # 起点URL
    start_urls = [
        'https://example.com',
        'https://another-example.com',
        'https://third-example.com'
    ]

    await crawler.run(start_urls)
    
    # データをJSONにエクスポート
    await crawler.export_data('./result.json')

if __name__ == '__main__':
    asyncio.run(main())

この拡張スクリプトでは以下のことが示されています:

  1. クローラーをさらにオプションで設定すること(ヘッドレスモード、ブラウザタイプ)。
  2. 各ページから複数のデータポイントを抽出すること(タイトル、コンテンツ、リンク)。
  3. context.enqueue_links()を使用して、発見したリンクを自動的にクロールキューに追加すること。
  4. 複数のURLからクローラーを起動すること。
  5. JSON形式でデータをエクスポートすること。

カスタムロジックの実装:フィルタリングと処理

特定のページのみ処理し、データを保存する前にカスタムロジックを追加しましょう。

import asyncio
from crawlee import PlaywrightCrawler, PlaywrightCrawlingContext
import re

async def main():
    crawler = PlaywrightCrawler(
        max_requests_per_crawl=200,
        headless=True
    )

    @crawler.router.default_handler
    async def request_handler(context: PlaywrightCrawlingContext):
        page = context.page
        url = page.url

        # 'blog'がURLに含まれているページのみ処理
        if 'blog' not in url:
            return

        title = await page.title()
        content = await page.evaluate('() => document.body.innerText')

        # 利用可能な場合は日付を抽出
        date_match = re.search(r'\d{4}-\d{2}-\d{2}', await page.content())
        date = date_match.group(0) if date_match else '不明'

        # コンテンツの処理:余分な空白を削除して切り捨て
        processed_content = ' '.join(content.split())[:1000]

        await context.push_data({
            'url': url,
            'title': title,
            'date': date,
            'content_preview': processed_content
        })

        # 'blog'を含むリンクのみクローリング対象にする
        await context.enqueue_links(
            glob_patterns=['**/blog/**', '**/blog*'],
            strategy='same-domain'
        )

    start_url = 'https://example-blog.com'
    await crawler.run([start_url])
    
    # データをCSVにエクスポート
    await crawler.export_data('./blog_data.csv')

if __name__ == '__main__':
    asyncio.run(main())

このスクリプトは以下を示しています:

  1. ブログページのみ処理するためのURLフィルタリング。
  2. データの抽出(コンテンツ内の日付の検出など)。
  3. コンテンツの処理(余分な空白の削除と切り捨て)。
  4. グロブパターンとドメイン戦略を使用した選択的なリンクキューへの追加。

異なるページタイプの処理

実際のシナリオでは、異なるタイプのページを別々に処理する必要がある場合があります。Crawleeのルーターを使用してこれを実現する方法は次のとおりです:

import asyncio
from crawlee import PlaywrightCrawler, PlaywrightCrawlingContext

async def main():
    crawler = PlaywrightCrawler(
        max_requests_per_crawl=300,
        headless=True
    )

    @crawler.router.match(pattern=r'/product/.*')
    async def product_handler(context: PlaywrightCrawlingContext):
        page = context.page
        
        product_name = await page.query_selector_eval('.product-name', 'el => el.textContent')
        price = await page.query_selector_eval('.price', 'el => el.textContent')
        description = await page.query_selector_eval('.description', 'el => el.textContent')

        await context.push_data({
            'type': 'product',
            'url': page.url,
            'name': product_name,
            'price': price,
            'description': description
        })

    @crawler.router.match(pattern=r'/category/.*')
    async def category_handler(context: PlaywrightCrawlingContext):
        page = context.page
        
        category_name = await page.query_selector_eval('.category-name', 'el => el.textContent')
        product_links = await page.evaluate('() => Array.from(document.querySelectorAll(".product-link")).map(a => a.href)')

        await context.push_data({
            'type': 'category',
            'url': page.url,
            'name': category_name,
            'product_count': len(product_links)
        })

        # クローリング対象の商品リンクをキューに追加
        for link in product_links:
            await context.enqueue_request(link)

    @crawler.router.default_handler
    async def default_handler(context: PlaywrightCrawlingContext):
        page = context.page
        
        title = await page.title()
        await context.push_data({
            'type': 'other',
            'url': page.url,
            'title': title
        })

        # ページ上のすべてのリンクをキューに追加
        await context.enqueue_links()

    start_url = 'https://example-store.com'
    await crawler.run([start_url])
    
    # データをJSONにエクスポート
    await crawler.export_data('./store_data.json')

if __name__ == '__main__':
    asyncio.run(main())

この例では次のことが実現されています:

  1. ルートパターンを使用して異なるページタイプ(商品、カテゴリ、その他)を処理すること。
  2. 各ページタイプの特定のデータを抽出すること。
  3. ページタイプに基づいた選択的なリンクのキューへの追加。
  4. 不明なページタイプのデフォルトハンドラでの処理。

ベストプラクティスとヒント

Robots.txtを尊重する:倫理的なスクレイピングを確保するために、ウェブサイトのrobots.txtファイルを確認して尊重してください。

適切な遅延を使用する:ターゲットサーバーを圧倒しないように、リクエスト間に適切な遅延を導入してください。

エラーを適切に処理する:予期せぬエラーを処理するためにtry-exceptブロックを使用し、クローラーが単一の失敗でクラッシュしないようにします。

クローラーの監視:Crawleeのログ機能を使用してクローラーの進行状況を監視し、問題を特定します。

ストレージの最適化:大規模なクロールには、Crawleeのストレージオプションを使用して収集するデータを効率的に管理することを検討してください。

最新情報を保つ:Crawleeのインストールを最新の状態に保ち、最新の機能とバグ修正の恩恵を受けるようにしてください。

プロキシのローテーションを使用する:広範なクローリングの場合は、IPブロックを回避するためにプロキシのローテーションを実装することを検討してください。

ユーザーエージェントの実装:ユーザーエージェントを回転させてリクエストをより自然に見せることができます。

結論

Crawlee-Pythonは、ウェブスクレイピングとブラウザ自動化のタスクに対する強力で柔軟な解決策を提供します。HTTPとヘッドレスブラウザの両方のクロールをサポートし、自動並列処理、堅牢なエラーハンドリングなどの豊富な機能セットにより、シンプルなスクレイピングプロジェクトから複雑なプロジェクトまで、効率的かつスケーラブルなウェブスクレイパーを構築するための優れた選択肢となります。

このガイドに示されている例とベストプラクティスに従うことで、Crawlee-Pythonを活用して効率的でスケーラブルで保守可能なウェブスクレイパーを構築することができます。データの抽出、ウェブサイトのモニタリング、検索エンジンの構築に関わらず、Crawlee-Pythonは目標を効果的に達成するために必要なツールを提供します。

ウェブサイトの利用規約や倫理的なガイドラインを尊重してスクレイピングを行うことを常に忘れずに行ってください。スクレイピングをお楽しみください!

💡
コードなしで独自のAgentic AIワークフローを作成したい場合は?

Anakin AIを使用すると、オンラインでビジュアルUIでAIワークフローを構築するパワーが得られます。GPT-4、Claude 3.5 Sonnet、Uncensored Dolphine Models、Stable Diffusion、DALLEなどの力を1つのワークフローに組み合わせることができます!

複雑なコーディングを忘れて、Anakin AIで日々の作業を自動化しましょう!
Anakin AIで簡単にAIエージェントワークフローを構築する
Anakin AIで簡単にAIエージェントワークフローを構築する