CrawleeによるWebスクレイピング – ステップバイステップガイド

Node.jsでCrawleeを使った効率的なウェブスクレイピングの方法を発見しましょう。基本的なセットアップから高度なプロキシローテーション、動的コンテンツの処理まで網羅しています。
5 分読
Web Scraping With Crawlee blog image

ウェブスクレイピングに興味があるなら、Crawleeが役立ちます。データサイエンティスト、開発者、研究者がウェブデータを収集するために使用する高速でインタラクティブなスクレイピングエンジンです。Crawleeはセットアップが簡単で、プロキシのローテーションやセッション管理などの機能を提供します。これらの機能は、IPアドレスがブロックされることなく、大規模または動的なウェブサイトをスクレイピングするために不可欠であり、スムーズで中断のないデータ収集を保証します。

このチュートリアルでは、Crawleeを使ったウェブスクレイピングの方法を学びます。基本的なウェブスクレイピングの例から始め、セッション管理や動的ページのスクレイピングなど、より高度な概念へと進みます。

CrawleeでWebスクレイピングする方法

このチュートリアルを始める前に、お使いのマシンに以下の前提条件がインストールされていることを確認してください:

  • Node.js
  • npm
  • Visual Studio Code

Crawleeによる基本的なWebスクレイピング

前提条件がすべて揃ったら、シンプルなHTML構造を提供しているため学習に最適なBooks to Scrapeウェブサイトのスクレイピングから始めましょう。

ターミナルまたはシェルを開き、以下のコマンドでNode.jsプロジェクトを初期化することから始めます:

mkdir crawlee-tutorial
cd crawlee-tutorial
npm init -y

次に、以下のコマンドでCrawleeライブラリをインストールします:

npm install crawlee

任意のウェブサイトからデータを効果的にスクレイピングするには、スクレイピングしたいウェブページを検査して、ウェブサイトのHTMLタグの詳細を取得する必要があります。そのためには、ブラウザでウェブサイトを開き、ウェブページ上の任意の場所を右クリックしてデベロッパーツールに移動します。次に、検証または要素を検証をクリックします:

Inspect HTML element

Elementsタブはデフォルトでアクティブになっており、このタブはウェブページのHTMLレイアウトを表しています。この例では、表示されているすべての本はproduct_podクラスを持つarticle HTMLタグに配置されています。各articleの中で、本のタイトルはh3タグに含まれています。本の実際のタイトルはh3要素内のaタグのtitle属性に含まれています。本の価格はprice_colorクラスを持つpタグの内側にあります:

Inspect the HTML elements on the Books to Scrape website

プロジェクトのルートディレクトリにscrape.jsという名前のファイルを作成し、以下のコードを追加します:

   const { CheerioCrawler } = require('crawlee');

   const crawler = new CheerioCrawler({
       async requestHandler({ request, $ }) {
           const books = [];
           $('article.product_pod').each((index, element) => {
               const title = $(element).find('h3 a').attr('title');
               const price = $(element).find('.price_color').text();
               books.push({ title, price });
           });
           console.log(books);
       },
   });

   crawler.run(['https://books.toscrape.com/']);

このコードでは、crawleeCheerioCrawlerを使用して、https://books.toscrape.com/から本のタイトルと価格をスクレイピングします。クローラーはHTMLコンテンツを取得し、jQueryライクな構文を使って<article class="product_pod">要素からデータを抽出し、結果をコンソールに記録します。

前述のコードをscrape.jsファイルに追加したら、以下のコマンドでコードを実行できます:

node scrape.js

本のタイトルと価格の配列がターミナルに出力されるはずです:

…output omitted…
  {
    title: 'The Boys in the Boat: Nine Americans and Their Epic Quest for Gold at the 1936 Berlin Olympics',
    price: '£22.60'
  },
  { title: 'The Black Maria', price: '£52.15' },
  {
    title: 'Starving Hearts (Triangular Trade Trilogy, #1)',
    price: '£13.99'
  },
  { title: "Shakespeare's Sonnets", price: '£20.66' },
  { title: 'Set Me Free', price: '£17.46' },
  {
    title: "Scott Pilgrim's Precious Little Life (Scott Pilgrim #1)",
    price: '£52.29'
  },
…output omitted…

Crawleeによるプロキシローテーション

プロキシはコンピュータとインターネットの間の仲介役です。プロキシを使用すると、ウェブリクエストがプロキシサーバーに送信され、そこからターゲットのウェブサイトに転送されます。プロキシサーバーはウェブサイトからのレスポンスを返し、プロキシはIPアドレスを隠してレート制限やIPバンを防ぎます。

Crawleeはプロキシの実装を容易にします。なぜなら、リトライやエラーを効率的に処理する組み込みのプロキシ処理が付属しているからです。Crawleeはまた、ローテーションプロキシを実装するための様々なプロキシ設定もサポートしています。

以下のセクションでは、まず有効なプロキシを取得してプロキシを設定します。次に、リクエストがプロキシを経由していることを確認します。

プロキシの設定

無料のプロキシは一般的に推奨されません。速度が遅く安全性に問題があり、機密性の高いウェブタスクに必要なサポートが不足している場合があるからです。代わりに、安全で安定した信頼性の高いプロキシサービスであるBright Dataの使用を検討してください。無料トライアルも提供しているので、コミットする前にテストすることができます。

Bright Dataを使用するには、ホームページ無料トライアルボタンをクリックし、必要な情報を入力してアカウントを作成します。

アカウントが作成されたら、Bright Dataダッシュボードにログインし、プロキシ&スクレイピングインフラに移動して、レジデンシャルプロキシを選択して新しいプロキシを追加します:

Add a residential proxy

デフォルト設定を維持し、追加をクリックしてレジデンシャルプロキシの作成を完了します。

証明書のインストールを求められた場合は、証明書なしで続行を選択できます。ただし、本番環境や実際のユースケースでは、プロキシ情報が漏洩した場合の悪用を防ぐために証明書を設定する必要があります。

作成後、ホスト、ポート、ユーザー名、パスワードを含むプロキシの認証情報をメモしてください。これらは次のステップで必要になります:

Bright Data proxy credentials

プロジェクトのルートディレクトリで、以下のコマンドを実行してaxiosライブラリをインストールします:

npm install axios

axiosライブラリを使用してhttp://lumtest.com/myip.jsonにGETリクエストを行います。これにより、スクリプトを実行するたびに使用しているプロキシの詳細が返されます。

次に、プロジェクトのルートディレクトリにscrapeWithProxy.jsという名前のファイルを作成し、以下のコードを追加します:

const { CheerioCrawler } = require("crawlee");
const { ProxyConfiguration } = require("crawlee");
const axios = require("axios");

const proxyConfiguration = new ProxyConfiguration({
  proxyUrls: ["http://USERNAME:PASSWORD@HOST:PORT"],
});

const crawler = new CheerioCrawler({
  proxyConfiguration,
  async requestHandler({ request, $, response, proxies }) {
    // Make a GET request to the proxy information URL
    try {
      const proxyInfo = await axios.get("http://lumtest.com/myip.json", {
        proxy: {
          host: "HOST",
          port: PORT,
          auth: {
            username: "USERNAME",
            password: "PASSWORD",
          },
        },
      });
      console.log("Proxy Information:", proxyInfo.data);
    } catch (error) {
      console.error("Error fetching proxy information:", error.message);
    }

    const books = [];
    $("article.product_pod").each((index, element) => {
      const title = $(element).find("h3 a").attr("title");
      const price = $(element).find(".price_color").text();
      books.push({ title, price });
    });
    console.log(books);
  },
});

crawler.run(["https://books.toscrape.com/"]);

注意: HOSTPORTUSERNAMEPASSWORDを必ずご自身の認証情報に置き換えてください。

このコードでは、指定したプロキシを使用してhttps://books.toscrape.com/から情報をスクレイピングするために、crawleeCheerioCrawlerを使用しています。ProxyConfigurationでプロキシを設定し、http://lumtest.com/myip.jsonへのGETリクエストを使用してプロキシの詳細を取得・記録します。最後に、CheerioのjQueryライクな構文を使って本のタイトルと価格を抽出し、スクレイピングしたデータをコンソールに記録します。

コードを実行してプロキシが機能していることを確認します:

node scrapeWithProxy.js

以前と同様の結果が表示されますが、今回はリクエストがBright Dataのプロキシを経由しています。コンソールにプロキシの詳細も表示されるはずです:

Proxy Information: {
  country: 'US',
  asn: { asnum: 21928, org_name: 'T-MOBILE-AS21928' },
  geo: {
    city: 'El Paso',
    region: 'TX',
    region_name: 'Texas',
    postal_code: '79925',
    latitude: 31.7899,
    longitude: -106.3658,
    tz: 'America/Denver',
    lum_city: 'elpaso',
    lum_region: 'tx'
  }
}
[
  { title: 'A Light in the Attic', price: '£51.77' },
  { title: 'Tipping the Velvet', price: '£53.74' },
  { title: 'Soumission', price: '£50.10' },
  { title: 'Sharp Objects', price: '£47.82' },
  { title: 'Sapiens: A Brief History of Humankind', price: '£54.23' },
  { title: 'The Requiem Red', price: '£22.65' },
…output omitted..

node scrapingWithBrightData.jsでスクリプトを再度実行すると、Bright Dataプロキシサーバーが使用する異なるIPアドレスの場所が表示されるはずです。これにより、Bright Dataがスクレイピングスクリプトを実行するたびに場所とIPをローテーションしていることが確認できます。このローテーションは、ターゲットウェブサイトからのブロックやIPバンを回避するために重要です。

注意: proxyConfigurationでは異なるプロキシIPを渡すこともできますが、Bright Dataがそれを代行してくれるため、IPを指定する必要はありません。

Crawleeによるセッション管理

セッションは複数のリクエストにわたって状態を維持するのに役立ちます。これはクッキーやログインセッションを使用するウェブサイトに便利です。

セッションを管理するには、プロジェクトのルートディレクトリにscrapeWithSessions.jsという名前のファイルを作成し、以下のコードを追加します:

const { CheerioCrawler, SessionPool } = require("crawlee");

(async () => {
  // Open a session pool
  const sessionPool = await SessionPool.open();

  // Ensure there is a session in the pool
  let session = await sessionPool.getSession();
  if (!session) {
    session = await sessionPool.createSession();
  }

  const crawler = new CheerioCrawler({
    useSessionPool: true, // Enable session pool
    async requestHandler({ request, $, response, session }) {
      // Log the session information
      console.log(`Using session: ${session.id}`);

      // Extract book data and log it (for demonstration)
      const books = [];
      $("article.product_pod").each((index, element) => {
        const title = $(element).find("h3 a").attr("title");
        const price = $(element).find(".price_color").text();
        books.push({ title, price });
      });
      console.log(books);
    },
  });

  // First run
  await crawler.run(["https://books.toscrape.com/"]);
  console.log("First run completed.");

  // Second run
  await crawler.run(["https://books.toscrape.com/"]);
  console.log("Second run completed.");
})();

ここでは、crawleeCheerioCrawlerSessionPoolを使用してhttps://books.toscrape.com/からデータをスクレイピングしています。セッションプールを初期化し、このセッションを利用するようにクローラーを設定します。requestHandler関数はセッション情報を記録し、CheerioのjQueryライクなセレクターを使って本のタイトルと価格を抽出します。コードは2回連続してスクレイピングを実行し、各実行でセッションIDを記録します。

コードを実行して、異なるセッションが使用されていることを確認します:

node scrapeWithSessions.js

以前と同様の結果が表示されますが、今回は各実行のセッションIDも表示されるはずです:

Using session: session_GmKuZ2TnVX
[
  { title: 'A Light in the Attic', price: '£51.77' },
  { title: 'Tipping the Velvet', price: '£53.74' },
…output omitted…
Using session: session_lNRxE89hXu
[
  { title: 'A Light in the Attic', price: '£51.77' },
  { title: 'Tipping the Velvet', price: '£53.74' },
…output omitted…

コードを再度実行すると、異なるセッションIDが使用されていることが確認できます。

Crawleeによる動的コンテンツの処理

動的なウェブサイトつまりJavaScriptによってコンテンツが生成されるウェブサイト)を扱う場合、データにアクセスするためにJavaScriptをレンダリングする必要があるため、ウェブスクレイピングは非常に困難になります。このような状況に対処するために、CrawleeはJavaScriptをレンダリングし、人間と同様にターゲットウェブサイトと対話できるヘッドレスブラウザであるPuppeteerと統合しています。

この機能を実演するために、このYouTubeページのコンテンツをスクレイピングしましょう。いつものように、何かをスクレイピングする前に、そのページのルールと利用規約を必ず確認してください。

利用規約を確認したら、プロジェクトのルートディレクトリにscrapeDynamicContent.jsという名前のファイルを作成し、以下のコードを追加します:

const { PuppeteerCrawler } = require("crawlee");

async function scrapeYouTube() {
  const crawler = new PuppeteerCrawler({
    async requestHandler({ page, request, enqueueLinks, log }) {
      const { url } = request;
      await page.goto(url, { waitUntil: "networkidle2" });

      // Scraping first 10 comments
      const comments = await page.evaluate(() => {
        return Array.from(document.querySelectorAll("#comments #content-text"))
          .slice(0, 10)
          .map((el) => el.innerText);
      });

      log.info(`Comments: ${comments.join("n")}`);
    },

    launchContext: {
      launchOptions: {
        headless: true,
      },
    },
  });

  // Add the URL of the YouTube video you want to scrape
  await crawler.run(["https://www.youtube.com/watch?v=wZ6cST5pexo"]);
}

scrapeYouTube();

次に、以下のコマンドでコードを実行します:

node scrapeDynamicContent.js

このコードでは、CrawleeライブラリのPuppeteerCrawlerを使用してYouTube動画のコメントをスクレイピングします。特定のYouTube動画のURLに移動し、ページが完全にロードされるのを待つクローラーを初期化することから始めます。ページがロードされると、コードはページコンテンツを評価し、指定されたCSSセレクター#comments #content-textを使って最初の10件のコメントを抽出します。コメントはコンソールに記録されます。

出力には、選択した動画に関連する最初の10件のコメントが含まれるはずです:

INFO  PuppeteerCrawler: Starting the crawler.
INFO  PuppeteerCrawler: Comments: Who are you rooting for?? US Marines or Ex Cons 
Bro Mateo is a beast, no lifting straps, close stance.
ex convict doing the pushups is a monster.
I love how quick this video was, without nonsense talk and long intros or outros
"They Both have combat experience" is wicked 
That military guy doing that deadlift is really no joke.. ...
One lives to fight and the other fights to live.
Finally something that would test the real outcome on which narrative is true on movies
I like the comradery between all of them. Especially on the Bench Press ... Both team members quickly helped out on the spotting to protect from injury. Well done.
I like this style, no youtube funny business. Just straight to the lifts
…output omitted…

このチュートリアルで使用したすべてのコードはGitHubで確認できます。

まとめ

この記事では、ウェブスクレイピングにCrawleeを使用する方法を学び、ウェブスクレイピングプロジェクトの効率性と信頼性を向上させる方法を確認しました。

データをスクレイピングする際は、ターゲットウェブサイトのrobots.txtファイルと利用規約を常に尊重することを忘れないでください。

プロフェッショナルグレードのデータ、ツール、プロキシでウェブスクレイピングプロジェクトを向上させる準備はできていますか?Bright Dataの包括的なウェブスクレイピングインフラを探索してみましょう。すぐに使えるデータセット高度なプロキシサービスを提供し、データ収集の効率化をサポートします。

今すぐサインアップして無料トライアルを始めましょう!