VisualStudio+WinFormの環境で、AngleSharpパッケージを利用したWebページのスクレイピングを行ってみます。
AngleSharpを使えるようにする
AngleSharpは、NuGetパッケージとして提供されているので、パッケージのインストールで導入することができます。AngleSharpのパッケージは下記の手順でインストールできます。
検索エリアに"AngleSharp"と入力して、結果に表示された"AngleSharp"パッケージをインストールします
プロジェクトの参照設定に"AngleSharp"が追加されていることを確認します
Formのレイアウトを作る
AngleSharpパッケージのインストールができたら、次はFormの画面を作ります。
今回は動作確認のため、以下のようにButtonとTextBoxを1つづつ配置したフォームを用意しました。
AngleSharpのSimpleDemoコードをWinFormから実行する
ボタンをクリックしたときのイベントハンドラを実装します。
getTitles()の中身は、AngleSharpのgithubページ(https://github.com/AngleSharp/AngleSharp)の内容をそのままコピーしています。
また、サンプルのコードは非同期処理で実行されているのでbutton1_Click()メソッドをasyncにしています。
namespace Test {
public partial class Form1 :Form {
public Form1() {
InitializeComponent();
}
/**
* ボタンクリック時のハンドラ
*/
private async void button1_Click( object sender, EventArgs e ) {
var titles = await getTitles();
foreach (var title in titles ) {
textBox1.AppendText( title + Environment.NewLine );
}
}
/**
* The Big Bang Theoryのタイトル一覧をWikipediaから取得する
*/
private async Task<System.Collections.Generic.IEnumerable<string>> getTitles() {
// Setup the configuration to support document loading
var config = Configuration.Default.WithDefaultLoader();
// Load the names of all The Big Bang Theory episodes from Wikipedia
var address = "https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes";
// Asynchronously get the document in a new context using the configuration
var document = await BrowsingContext.New( config ).OpenAsync( address );
// This CSS selector gets the desired content
var cellSelector = "tr.vevent td:nth-child(3)";
// Perform the query to get all cells with the content
var cells = document.QuerySelectorAll( cellSelector );
// We are only interested in the text - select it with LINQ
var titles = cells.Select( m => m.TextContent );
return titles;
}
}
}
実行結果を確認する
プログラムを実行し、ソースコードの記載のページ(https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes)のタイトル一覧が出力されればOKです。
サンプルコードを少しだけ使いやすくする
せっかく動作確認のアプリケーションを作ったので、少しだけ改善して汎用的に使えるようにしてみます。
FormでURLをセレクタを指定可能に
先ほどの例ではURLとセレクタがプログラム中に記載されていたため、Formから指定できるようにします。
Formから指定された情報で検索を行う
次に、指定されたURLとセレクタを元に検索が行えるようにします。
private async void button1_Click( object sender, EventArgs e ) {
var url = txtUrl.Text;
var selector = txtSelector.Text;
var titles = await getTitles(url, selector);
foreach (var title in titles ) {
textBox1.AppendText( title + Environment.NewLine );
}
}
/**
* 指定されたURLからスクレイピングを行う
*/
private async Task<System.Collections.Generic.IEnumerable<string>> getTitles(string url, string selector ) {
// Setup the configuration to support document loading
var config = Configuration.Default.WithDefaultLoader();
// Asynchronously get the document in a new context using the configuration
var document = await BrowsingContext.New( config ).OpenAsync( url );
// Perform the query to get all cells with the content
var cells = document.QuerySelectorAll( selector );
// We are only interested in the text - select it with LINQ
var titles = cells.Select( m => m.TextContent );
return titles;
}
この変更で、任意のページからスクレイピングが行えるようになりました。
StackOverflowの記事を検索してみる
例えば、URLとセレクタを以下のように指定するだけで、stackoverflow.comから最近の質問一覧を取得することができるようになります。
URL https://stackoverflow.com/questions/tagged/c%23
セレクタ div#questions h3
ブラウザで指定したURLを開くと以下のように表示されるので、たしかに質問のタイトル一覧が抽出できていることが分かります。