Visual C# 2005でネットワークプログラミング 01 URIの構造解析&HTMLソースの取得

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]

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です