【C#】Selenium を使ったWebスクレイピング

Selenium というツールを使うことで、RPAのようにWebアプリケーションのテストを自動化したり、任意のWebサイトからスクレイピングでHTML上のデータを抽出することが可能です。
仕組みとしては、Chromeをプログラムで起動して、動作を制御したりHTMLを読み取ってデータを取得などを行います。対応言語は様々で、C#にも対応しています。

APIなどでデータを提供しているWebサイトであれば利用することはあまり無いと思いますが、APIを提供していない場合はWebスクレイピングをしなければデータを取得することができません。ただしスクレイピングでデータ取得することを禁止しているサイトもあるため、利用には注意が必要です。

今回はSeleniumを使ってWebスクレイピングを試してみます。

【検証環境】Visual Studio 2022 / コンソールアプリ / Chrome Ver 101.0.4951.41 /

Selenium

スクレイピングの注意点

下記注意点となります。気を付けましょう。

・Webサイトの利用規約に違反する(利用規約で触れている場合は違反になる)

・サーバに過度の負荷をかける(アクセス不能になり業務妨害にあたる)

著作権を侵害する(抽出したデータを無断で公開・販売するなど)

https://www.octoparse.jp/blog/10-myths-about-web-scraping/#div1

Selenium の利用準備

パッケージのインストール

下記2つのパッケージをインストールします

  • Selenium.WebDriver
  • Selenium.Support

Webブラウザドライバーのダウンロード

下記リンクからChromeのバージョンと同じドライバーをダウンロードしますhttps://chromedriver.storage.googleapis.com/index.html

※バージョンが異なるとエラーになります

Chromeのバージョンは 設定 > Chromeについて から確認できます

ダウンロードしたZipファイルを解凍するとexeファイルがありますので、プロジェクト直下に追加します
(※プロジェクト直下でなければプログラムでパスを明記する必要があります)

プロパティからビルドアクションを「コンテンツ」、出力ディレクトリにコピーを「新しい場合はコピーする」に変更します

これでSeleniumを利用する準備は完了です

Selenium の使い方

このブログのトップページを対象にしてデータを取得してみます。
下記画像の最新記事からタイトルを抽出してみます。

詳しい使い方は公式のドキュメントを参照ください。

基本的にidやclass名などから要素を取得します。スクレイピングを行う場合はHTMLの構造を把握しておく必要があります。HTMLの構造はデベロッパーツールで確認しましょう。

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

// ドライバ起動
using (var driver = new ChromeDriver())
{
    // 対象のURL
    var url = "https://pg-life.net/";

    // URLへ遷移
    driver.Navigate().GoToUrl(url);

    // idで要素を取得
    var newEntryBox = driver.FindElement(By.Id("new-entry-box"));
    // classで要素を取得(複数あるためFindElements)
    var newEntryItems = newEntryBox.FindElements(By.ClassName("new-entry-item"));
    // 複数要素をループで一つずつ出力
    foreach (var item in newEntryItems)
    {
        // classで要素を取得(単一のためFindElement)
        var newEntryItemMeta = item.FindElement(By.ClassName("new-entry-item-meta"));
        // Textプロパティで文言を出力
        Console.WriteLine(newEntryItemMeta.Text);
    }
}

取得できたことが確認できました。

ドライバのパス指定

ドライバをプロジェクト直下にしたくない場合はプログラムでパスを指定する必要があります。

// プロジェクト直下
var baseDirectry = AppDomain.CurrentDomain.BaseDirectory;
// ドライバが存在するディレクトリ
var pathToDriver = $@"{baseDirectry}/driver";
using (var driverService = ChromeDriverService.CreateDefaultService(pathToDriver))
{
    // ドライバ起動
    using (var driver = new ChromeDriver(driverService))
    {
        // 処理
    }
}

コマンドプロンプトを非表示にする

driverServiceのコマンドプロンプトを表示したくない場合は、ドライバの起動前にHideCommandPromptWindow を true にします。

using (var driverService = ChromeDriverService.CreateDefaultService(pathToDriver))
{
    // プロンプトを出さないようにする
    driverService.HideCommandPromptWindow = true;

    // ドライバ起動
    using (var driver = new ChromeDriver(driverService))
    {
        // 処理
    }
}

Chrome を非表示にする

ドライバを起動するとChromeブラウザが開かれますが、非表示にすることも可能です。

using (var driverService = ChromeDriverService.CreateDefaultService(pathToDriver))
{
    // 起動オプションの設定
    var options = new ChromeOptions();

    // ヘッドレス(画面なし)
    options.AddArgument("--headless");

    // ドライバ起動
    using (var driver = new ChromeDriver(driverService, options))
    {
        // 処理
    }
}

画面の操作

要素の取得だけでなく、画面を操作することも可能です。

検索ボックスに「IIS」と入力して、フォームを送信してみます。

// 対象のURL
var url = "https://pg-life.net/";

// ドライバ起動
var driver = new OpenQA.Selenium.Chrome.ChromeDriver();
// URL遷移
driver.Navigate().GoToUrl(url);

// 検索ボックス要素
var searchForm = driver.FindElement(By.Id("s"));
// 文字を入力
searchForm.SendKeys("IIS");
// 送信
searchForm.Submit();


///// 送信はボタン要素を取得してクリックする下記のやり方でも可能
// 検索ボタン要素
// var searchSubmit = driver.FindElement(By.Id("searchsubmit"));
// クリック
// searchSubmit.Click();

画面操作ができたことが確認できました。

Leave a Reply

Your email address will not be published. Required fields are marked *