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]