webブラウザを自作したい!(3)
今回は前回言ってたように戻る進む再読込とかとか
・
・
・
・
ではなく、「サイトのアイコンを適用する」です。
サイトのアイコンを適用する
え?それだけ?
はいそれだけです(それ以外にもちょっとあるよ)
コレがわりと苦労しました。
簡単そうに見えてこれ持ってるプロパティとかなさそうで、html内部からURL探して持ってくる必要がありました。
もっといい方法ありそうですが、とりあえずぶん殴る形式になっちゃいました。知ってる人おしえてください・・・><
それではSSから
まあこんな感じで変わってますね。
ソースコード
private void Browser_Navigated( object sender, WebBrowserNavigatedEventArgs e ) { //this.Text = browser.DocumentTitle; this.urlBox.Text = browser.Url.ToString(); string iconUrl = getIconUrl( e ); this.Icon = getIcon( iconUrl ); } private string getIconUrl( WebBrowserNavigatedEventArgs e ) { foreach( HtmlElement linkTag in this.browser.Document.GetElementsByTagName("link") ) { string relAttribute = linkTag.GetAttribute("rel"); string iconUrl; if( relAttribute == "shortcut icon" || relAttribute == "icon" ) { iconUrl = linkTag.GetAttribute("href"); if( iconUrl.StartsWith("http") ) return iconUrl; else if( iconUrl.StartsWith("/") ) return "http://" + e.Url.Host + iconUrl; else return e.Url.ToString() + iconUrl; } } return "http://" + e.Url.Host + "/favicon.ico"; } //url -> Icon private Icon getIcon( string url ) { WebClient webClient = new WebClient(); using( MemoryStream stream = new MemoryStream( webClient.DownloadData( url ) ) ) { Icon icon = new Icon( stream ); return icon; } } private void Browser_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e ) { this.Text = browser.DocumentTitle; }
ざっくりいじった所だけ貼りました。
getIconUrl()でアイコンのURLを引っぱってきて、getIcon()でURLからアイコンを取得する感じです。
private string getIconUrl( WebBrowserNavigatedEventArgs e ) { foreach( HtmlElement linkTag in this.browser.Document.GetElementsByTagName("link") ) { string relAttribute = linkTag.GetAttribute("rel"); string iconUrl; if( relAttribute == "shortcut icon" || relAttribute == "icon" ) { iconUrl = linkTag.GetAttribute("href"); if( iconUrl.StartsWith("http") ) return iconUrl; else if( iconUrl.StartsWith("/") ) return "http://" + e.Url.Host + iconUrl; else return e.Url.ToString() + iconUrl; } } return "http://" + e.Url.Host + "/favicon.ico"; }
ホントにぶん殴りコードですね・・・^^;
とりあえずlinkタグのやつを全部抽出してその中のrel探してきて、その属性がicon系なら引っ張るって感じですね。
それでも無かったらfavicon.icoにあるんじゃねってことで最後です。
C#でスクレイピングしたこと無かったので苦戦しました・・・。
でも完成してみたら、割りと読みやすいというかわかりやすいコードになりました。
もっといい方法ないかなぁ(ボソッ
private Icon getIcon( string url ) { WebClient webClient = new WebClient(); using( MemoryStream stream = new MemoryStream( webClient.DownloadData( url ) ) ) { Icon icon = new Icon( stream ); return icon; } }
getIcon()はurlからアイコンを持ってくるメソッドです。
urlの示すデータを読み込んで、それをアイコンとして読み出す、ってイメージでしょうか。
んでそれらを↓でまとめるって感じになってます。
private void Browser_Navigated( object sender, WebBrowserNavigatedEventArgs e ) { //this.Text = browser.DocumentTitle; this.urlBox.Text = browser.Url.ToString(); string iconUrl = getIconUrl( e ); //url持ってきて this.Icon = getIcon( iconUrl ); //アイコンにする }
ここで気がついた人もいるかもですが、タイトルを取得するイベントを
WebBrowser.Navigated()
↓
WebBrowser.DocumentCompleted()
に変更しました。
Navigatedだとまだサイトに案内できただけで、中身をすべてロードできていない(?)状態らしいです。
実際に、Navigatedだとタイトルを取得できないサイトが複数ありました。(←これはタイミングの問題でもあるかも)
DocumentCompletedは、サイトの中身のロードが完了すると発生するイベントなので、これを利用しようという結論になりました。これだと全部タイトルがしっかり適用されました。
大した変更じゃないけど、結構重要なのでやっておきました。
それでは今回はここまで。
次回こそは、戻る進む再読込つくろう!(全然難しくないんだけどね())