Visual C#を使ってネットワークプログラミングするシリーズ
本シリーズはC#でGoogleマップ等のWebAPIを使おうというのが目的です。
第1回である今回は、指定されたURIの構造解析、HTMLソースを取得してみます。
URI構造解析&HTMLソース取得ツール
概要
指定したURLからHTMLソースを取得し、種々の情報を表示させます。
画面構成
URIの構造
http://<ホスト>[:<ポート>]<パス>[?<クエリー>][#<フラグメント>]
・System名前空間Uriクラスを利用することでURIの各要素を取得できる。
Uri myUri = new Uri("http://URL/"); textBoxScheme.Text = myUri.Scheme; textBoxHost.Text = myUri.Host; textBoxPort.Text = myUri.Port.ToString(); textBoxAbsolutePath.Text = myUri.AbsolutePath; textBoxQuery.Text = myUri.Query; textBoxPassAndQuery.Text = myUri.PathAndQuery; textBoxFragment.Text = myUri.Fragment;
HTMLソースの取得
・System.Net名前空間 WebClient.DownloadString(“http://URL/”)メソッドで行う。
・文字コードは指定しなければデフォルトのshift-jis形式で行われる。
文字コードの指定
・DownloadStringメソッド使用前に、WebClient.Encodingプロパティに
Encodingオブジェクトを指定しておく。
・Encodingオブジェクトは、System.Text名前空間 Encoding.GetEncoding(“文字コード名”)で生成する。
・主な文字コードとして、shift-jis、、euc-jp、utf-8がある。
文字コードの判定
・文字コードがあらかじめわかっていない場合(がほとんどなので)、
いったんASCIIエンコードでHTMLソースを取得しておく。
WehClient.DownloadDataメソッドでbyte配列として取得、
Encoding.ASCII.GetString()メソッドでASCIIエンコードした文字列を取得。
・以下のような<meta>タグ内のcharsetの指定を抽出して文字コードを判定。
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
・判定した文字コードでWebClient.DownloadStringする。
(metaタグがない場合はあきらめる(デフォルトのshift-jisとする))。
→metaタグによらず文字コード判定する方法が見つかるまで保留。
正規表現
・<meta>タグ内のcharsetの指定は正規表現でマッチング、抽出する。
・System.Text.RegularExpressions名前空間 Regex.Matchメソッドにより
マッチング結果を格納したMatchオブジェクトを得る。
・Match.Successプロパティにより、マッチング成功かどうか判定する。
・Match.Groups[]プロパティにマッチングした文字列を取得する。
byte[] data = myCliant.DownloadData("http://URL/");/* コンテンツをバイト配列にダウンロード */ String s = Encoding.ASCII.GetString(data);/* バイト配列をASCIIエンコードで文字列に変換 */ Match mymatch = Regex.Match(s, @"<metas+[^>]*charsets*=s*([-_w]+)",/* 括弧で囲んだ部分を抽出 */ RegexOptions.IgnoreCase); /* 大文字小文字区別しない */ String e = mymatch.Success ? mymatch.Groups[1].Value : "shift-jis"; /* 抽出結果はGroupsで取得 */
コード
private void buttonGet_Click(object sender, EventArgs e) { if (Uri.IsWellFormedUriString(textBoxURL.Text, UriKind.Absolute)) { Uri myUri = new Uri(textBoxURL.Text); /* URIの構成 */ textBoxScheme.Text = myUri.Scheme; textBoxHost.Text = myUri.Host; textBoxPort.Text = myUri.Port.ToString(); textBoxAbsolutePath.Text = myUri.AbsolutePath; textBoxQuery.Text = myUri.Query; textBoxPassAndQuery.Text = myUri.PathAndQuery; textBoxFragment.Text = myUri.Fragment; WebClient myCliant = new WebClient(); Encoding encoding = Encoding.GetEncoding("shift-jis"); /* コンテンツのエンコード方式 */ if (radioButtonShift_Jis.Checked) { encoding = Encoding.GetEncoding("shift-jis"); } else if (radioButtonEUC_JP.Checked) { encoding = Encoding.GetEncoding("euc-jp"); } else if (radioButtonUTF_8.Checked) { encoding = Encoding.GetEncoding("utf-8"); } else if (radioButtonAuto.Checked) { /* コンテンツをバイト配列にダウンロード */ byte[] data = myCliant.DownloadData(textBoxURL.Text); encoding = myDetectEncoding(data);/* エンコード方式を判定 */ } myCliant.Encoding = encoding; textBoxHTML.Text = myCliant.DownloadString(textBoxURL.Text); textBoxCharSet.Text = encoding.WebName; } else { MessageBox.Show("無効なURLです。", Text, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private Encoding myDetectEncoding(byte[] data) { /* バイト配列をASCIIエンコードで文字列に変換 */ String s = Encoding.ASCII.GetString(data); /* <meta>タグを抽出するための正規表現 */ Match mymatch = Regex.Match(s, @"<metas+[^>]*charsets*=s*([-_w]+)", RegexOptions.IgnoreCase); String e = mymatch.Success ? mymatch.Groups[1].Value : "shift-jis"; return Encoding.GetEncoding(e); }
memo
今回のツール作成で得たチップスをメモリます。
チップス集として別記事にまとめるかもしれません。
usingディレクティブを自動で追加する方法
usingディレクティブを追加していない状態でビルド実行すると、
コンパイルエラーとして、赤線が引かれる。
以下方法で自動でusingディレクティブが追加される。
・赤線部分で右クリック->競合の解決
・赤線部分でスマートタグを表示させて選択
・赤線部分で[Shift]+[Alt]+[F10]