これまでwebスクレーピングではSelenium.Chrome.WebDriverを使ってきました。ところがこの方法はインストールされているGoogle ChromeとDriverのバージョンがあっていないとうまく動いてくれません。またアプリを使用しようとしているパソコンにGoogle Chromeがインストールされていない可能性も考えられます。
そこで今回はPuppeteerSharpを使います。Google Chromeが実行ファイルがあるフォルダにインストールされるので、これならGoogle Chromeがインストールされていないパソコンやバージョンが合わないという問題を気にする必要がなくなります。ただ実行ファイルがあるフォルダのなかのファイル数が多くなり、ファイルサイズも大きくなってしまいます。
それではやってみましょう。以下はYahooJapanのトップページのhtmlを取得するコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using PuppeteerSharp; public partial class Form1 : Form { private async void button1_Click(object sender, EventArgs e) { await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); Browser browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true, }); Page page = await browser.NewPageAsync(); await page.GoToAsync("https://www.yahoo.co.jp/"); string html = await page.GetContentAsync(); await page.DisposeAsync(); await browser.DisposeAsync(); } } |
実際に実行してみると表示に時間がかかります。初回起動ではchromeのダウンロードがおこなわれるため、時間がかかるのです。時間がかかるのは最初だけで、2回目以降はそんなに時間はかかりません。
それからフォルダ内のファイルサイズがかなり大きくなります。調べてみると333MBもありました。
PuppeteerSharpを使うとスクリーンショットを撮ることもできます。以下のコードでスクリーンショットが撮れます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using PuppeteerSharp; public partial class Form1 : Form { private async void button1_Click(object sender, EventArgs e) { await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); Browser browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false, }); Page page = await browser.NewPageAsync(); await page.GoToAsync("https://www.yahoo.co.jp/"); await page.ScreenshotAsync("abc1.png"); await page.DisposeAsync(); await browser.DisposeAsync(); } } |
大きさは40%に縮小しています。
またSetViewportAsyncメソッドで大きさを変更することもできます。以下は幅1000ピクセル、高さ5000ピクセルでスクリーンショットを撮るコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public partial class Form1 : Form { private async void button1_Click(object sender, EventArgs e) { await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); Browser browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true, }); Page page = await browser.NewPageAsync(); ViewPortOptions options = new ViewPortOptions(); options.Width = 1000; options.Height = 5000; await page.SetViewportAsync(options); await page.GoToAsync("https://www.yahoo.co.jp/"); System.Threading.Thread.Sleep(5000); await page.ScreenshotAsync("abc2.png"); await page.DisposeAsync(); await browser.DisposeAsync(); } } |
大きさは40%に縮小しています。
スクロールさせるにはQuerySelectorAsyncメソッドやQuerySelectorAllAsyncメソッドでElementHandleを取得してElementHandle.HoverAsync()メソッドを実行します。
以下のコードは少しずつスクロールさせながらスクリーンショットを撮っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public partial class Form1 : Form { private async void button1_Click(object sender, EventArgs e) { await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); Browser browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true, }); Page page = await browser.NewPageAsync(); ViewPortOptions options = new ViewPortOptions(); options.Width = 1000; options.Height = 1000; await page.SetViewportAsync(options); await page.GoToAsync("https://www.yahoo.co.jp/"); for (int i = 1; i <= 4; i++) { System.Threading.Thread.Sleep(2000); await page.ScreenshotAsync(string.Format("xyz{0}.png", i)); ElementHandle[] elementHandles = await page.QuerySelectorAllAsync("div._3JzPQNweNOi2PGgRhkTKjU"); ElementHandle elementHandle = elementHandles[i * 5]; await elementHandle.HoverAsync(); } await page.DisposeAsync(); await browser.DisposeAsync(); } } |
アンカーテキストやリンク先urlを取得するのであればGetPropertyAsync(“textContent”)とかGetPropertyAsync(“href”)とやれば取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public partial class Form1 : Form { private async void button1_Click(object sender, EventArgs e) { await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); Browser browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = false, }); Page page = await browser.NewPageAsync(); await page.GoToAsync("https://www.yahoo.co.jp/"); ElementHandle[] elementHandles = await page.QuerySelectorAllAsync("a"); foreach (ElementHandle element in elementHandles) { // 最初に"JSHandle:"が入るので最初の9文字は捨てる string str = element.GetPropertyAsync("textContent").Result.ToString().Substring(9); string url = element.GetPropertyAsync("href").Result.ToString().Substring(9); } await page.DisposeAsync(); await browser.DisposeAsync(); } } |