C# Programming

Image郵便番号−住所 検索ツール(同期型)

開発環境: Visual Studio 2003 

1.目次

  1. 目次
  2. 目的
  3. 参考書
  4. 郵政公社の郵便番号検索へのアクセス
  5. 郵便番号検索のHTML応答パターン
  6. POST の基本的な流れ
  7. 未解決問題
  8. ダウンロード
  9. ソースコード

2.目的

 

注意
これはHTTP POST, GETの実験のために、郵政公社を使ってみただけです。まねて、同じアプリを作らないように!!
手で検索するのと違って、プログラムで連続検索をかけるとサーバ側に相当な負荷をかけることができてしまいます。

.NETで作るんだったら、こんなことはせずに、郵便番号のCSVファイルを郵政公社からダウンロードして、データベースにぶち込む。それをXML Webサービスで公開して、XML Webサービス経由でアクセスするというのが正解。

すでにそのようなサービスがありますので、そちらを使いましょう。

Web アクセス時の POST データの受け渡し方法を調べていて、適当なテストできるサイトが無いか探していたところ、
郵政公社の郵便番号検索が POST を使っていたので、試しに作ってみました。
その結果、Web アクセス時の POST データの扱い、正規表現で、メモっておきたい情報があったので、まとめておきます。

作ったアプリケーションはこんな感じです。
Image

3.参考書

  1. 郵政公社の郵便番号検索のホームページ
  2. MSDN 正規表現言語要素
  3. MSDN RegEx
  4. C#プログラミング バリデーションへの応用例
  5. GotDotNet サンプル: ”タスクの例 : POST 要求を作成する”
  6. C#プログラミング RegEx 正規表現

4.郵政公社の郵便番号検索へのアクセス

郵政公社の郵便番号検索のホームページがあって、郵便番号を Web で検索できます。
http://www.post.japanpost.jp/zipcode/index.html

そのページは、POST によるHTMLスクリプトで動作しています。
そこで、WebRequest を使って、C# で POST データをプログラムから書き込み、
結果を受け取って、それを表示するようにしています。

注意
本来ならば、XML Web Service でこのような郵便番号検索機能が提供されていれば、何の問題も無いのですが、HTML でしか検索できません。
検索ページのHTML を調べて、その結果に基づいて処理た処理を行っています。
このため、該当ページが変更されてしまうと、動作しなくなります。

5.郵便番号検索のHTML応答パターン

この郵便番号検索を行うと、いろいろな応答パターンがあります。
このうち、このアプリケーションでハンドリングしているのは、次のパターンだけです。
処理には正規表現を使っています。

郵便番号 住所検索時の POST データ
"mode=search&start=0&end=400&keyword=123-1234&new=on"
ここで、検索したい郵便番号をkeyword=郵便番号で指定します。
郵便番号 住所検索時
番号が短すぎた場合番号が短すぎます
番号が短すぎた場合新番号の場合は5桁以上入れてください
該当数 12 件ヒットしたときの件数
住所の応答例(1件分)<TR><TD> 210-0854<BR>(210 )</TD><TD>カナガワケン<BR>神奈川県</TD>
<TD>カワサキシカワサキク<BR>川崎市川崎区</TD><TD>アサノチョウ<BR>浅野町"

住所 郵便番号検索時の POST データ
"text/plain&ken=県コード&city=市町村名&town=町域名"
県コードは、例えば東京、タイトウク、アサクサの場合は次のようになります。
"enctype=text/plain&ken=13&city=タイトウク&town=アサクサ"

注意: 空白や区切り記号などの文字が HTTP ストリームで渡される場合、それらの文字は受信側で誤って解釈される可能性があります。そこで、URL では使用できない文字を等価の文字エンティティに変換する必要があります。
したがって、実際にPOSTするデータは、次ぎようになります。

"enctype=text/plain&ken=13&city=%83%5e%83C%83g%83E%83N&town=%83A%83T%83N%83T"
住所 郵便番号の HTML 応答パターン
複数の県に住所が存在する場合該当する都道府県が複数あります。
市町村名が短すぎる場合市区町村名が短がすぎます
市町村名が短すぎる場合市区町村名が特定できませんでした。条件をみなおしてみてください
住所の応答例(1件分)<TR><TD>210-0854</TD><TD>神奈川県<BR><TD>カワサキシカワサキク<BR>川崎市川崎区</TD><TD>アサノチョウ<BR>浅野町</TD></TR>

このため、これらの応答パターンが変更になってしまうと、正しく動作できなくなります。

6.POST の基本的な流れ


デザインパターンと言うほどのものではありませんが、とりあえず ^^;
ただ、この場合非同期処理ではないので、実行時にフォームの描画が停止してしまいます。
非同期処理にしたほうがいいでしょう。

using System.Text;
using System.IO;
using System.Net;
using System.Web;
・・・
            Stream stream = null;
            StreamReader sr = null;
            try
            {
                WebRequest webReq = HttpWebRequest.Create( "http://....." );
                webReq.Method = "POST"; 
                webReq.Timeout = 1000000; // 1秒でタイムアウトさせる。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy(); // IE のプロキシ設定を使用する。
                webReq.ContentType = "application/x-www-form-urlencoded"; 
                // POST パラメータを書く。
                // 正確なパラメータを渡すために HttpUtility.UrlEncode()でエンコードする。
                string parameters = "enctype=text/plain&ken=";                
                parameters += GetKenCode(ken);
                parameters += "&city=";
                parameters += HttpUtility.UrlEncode(city, Encoding.GetEncoding("SHIFT-JIS"));
                parameters += "&town=";
                parameters += HttpUtility.UrlEncode(town, Encoding.GetEncoding("SHIFT-JIS"));
                StreamWriter sw = new StreamWriter(webReq.GetRequestStream(), Encoding.GetEncoding("SHIFT-JIS"));
                sw.Write(parameters);  // POSTデータを送る。
                sw.Close();

                WebResponse webRes = webReq.GetResponse();
                // HttpWebRequest からストリームを取得する。
                stream = webRes.GetResponseStream();
                // 1行ごとに扱いたいので、StreamReader にする。
                sr = new System.IO.StreamReader(stream, Encoding.GetEncoding("SHIFT-JIS"));
                String str;

                while( true )
                {
                    str = sr.ReadLine();
                    if (str == null)
                        break;                    
                }
            }
            catch (WebException)
            {
                // わけのわからないMessage が返ってくるので、わかりやすいメッセージに変える。
                throw(new WebException("xxxに接続できませんでした。"));
            }
            finally
            {
                if (sr != null) sr.Close();
                if (stream != null) stream.Close();
            }



7.未解決問題

Proxy 経由で無い場合はうまく動作しています。
しかし、Proxy 経由で試してみたら、動作しませんでした。

Proxy のところは、次のように IE のプロキシ設定を使用するようにしても、直接プロキシを指定するようにしてもだめでした。
webReq.Proxy = System.Net.WebProxy.GetDefaultProxy(); // IE のプロキシ設定を使用する。

また、http://ja.gotdotnet.com/quickstart/howto/doc/WebRequests/clientPOST.aspx
のサンプルコードにこのようにプロキシの設定をしてもだめでした。

しかし、プロキシ経由ではなくアクセスするとOKなので、ひょっとしてバグ?

8.ダウンロード

提供していません。

9.ソースコード

2003/5/18   初版作成

変更履歴
V1.0 ZipCodeForm.cs, ZipCodeUtil.cs, About.cs

ZipCodeForm.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using Uchukamen.Util.ZipCodeJapan;
using System.Configuration;

namespace ZipCode
{
    /// <summary>
    /// Form1 の概要の説明です。
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.TextBox tbZipCode;
        private System.Windows.Forms.TextBox tbCity;
        private System.Windows.Forms.TextBox tbTown;
        private System.Windows.Forms.Button btnSearchZip;
        private System.Windows.Forms.ComboBox cbKen;
        private System.Windows.Forms.ListBox listBox1;
        private System.Windows.Forms.Button btnSearchKana;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.ToolTip toolTip1;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Button btnClear;
        private System.Windows.Forms.ErrorProvider errorProvider1;
        private System.Windows.Forms.MainMenu mainMenu1;
        private System.Windows.Forms.MenuItem menuItem1;
        private System.Windows.Forms.MenuItem menuItem2;
        private System.Windows.Forms.ContextMenu contextMenu1;
        private System.Windows.Forms.MenuItem menuItem3;
        private System.Windows.Forms.StatusBar statusBar1;
        private System.Windows.Forms.StatusBarPanel statusBarPanel1;
        private System.ComponentModel.IContainer components;

        public Form1()
        {
            //
            // Windows フォーム デザイナ サポートに必要です。
            //
            InitializeComponent();

            //
            // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
            //
        }

        /// <summary>
        /// 使用されているリソースに後処理を実行します。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

                #region Windows Form Designer generated code
        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.btnSearchZip = new System.Windows.Forms.Button();
            this.tbZipCode = new System.Windows.Forms.TextBox();
            this.btnSearchKana = new System.Windows.Forms.Button();
            this.tbCity = new System.Windows.Forms.TextBox();
            this.tbTown = new System.Windows.Forms.TextBox();
            this.cbKen = new System.Windows.Forms.ComboBox();
            this.listBox1 = new System.Windows.Forms.ListBox();
            this.contextMenu1 = new System.Windows.Forms.ContextMenu();
            this.menuItem3 = new System.Windows.Forms.MenuItem();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.label4 = new System.Windows.Forms.Label();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.btnClear = new System.Windows.Forms.Button();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
            this.errorProvider1 = new System.Windows.Forms.ErrorProvider();
            this.mainMenu1 = new System.Windows.Forms.MainMenu();
            this.menuItem1 = new System.Windows.Forms.MenuItem();
            this.menuItem2 = new System.Windows.Forms.MenuItem();
            this.statusBar1 = new System.Windows.Forms.StatusBar();
            this.statusBarPanel1 = new System.Windows.Forms.StatusBarPanel();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).BeginInit();
            this.SuspendLayout();
            // 
            // btnSearchZip
            // 
            this.btnSearchZip.Anchor = (System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right);
            this.btnSearchZip.Location = new System.Drawing.Point(296, 24);
            this.btnSearchZip.Name = "btnSearchZip";
            this.btnSearchZip.Size = new System.Drawing.Size(48, 23);
            this.btnSearchZip.TabIndex = 2;
            this.btnSearchZip.Text = "検索";
            this.toolTip1.SetToolTip(this.btnSearchZip, "郵便番号より検索");
            this.btnSearchZip.Click += new System.EventHandler(this.btnSearchZip_Click);
            // 
            // tbZipCode
            // 
            this.tbZipCode.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.tbZipCode.Location = new System.Drawing.Point(104, 24);
            this.tbZipCode.Name = "tbZipCode";
            this.tbZipCode.Size = new System.Drawing.Size(56, 19);
            this.tbZipCode.TabIndex = 1;
            this.tbZipCode.Text = "";
            this.toolTip1.SetToolTip(this.tbZipCode, "例:123-4567");
            // 
            // btnSearchKana
            // 
            this.btnSearchKana.Anchor = (System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right);
            this.btnSearchKana.Location = new System.Drawing.Point(296, 24);
            this.btnSearchKana.Name = "btnSearchKana";
            this.btnSearchKana.Size = new System.Drawing.Size(48, 23);
            this.btnSearchKana.TabIndex = 2;
            this.btnSearchKana.Text = "検索";
            this.toolTip1.SetToolTip(this.btnSearchKana, "住所の読みがなより検索");
            this.btnSearchKana.Click += new System.EventHandler(this.button2_Click);
            // 
            // tbCity
            // 
            this.tbCity.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.tbCity.ImeMode = System.Windows.Forms.ImeMode.Katakana;
            this.tbCity.Location = new System.Drawing.Point(104, 56);
            this.tbCity.Name = "tbCity";
            this.tbCity.Size = new System.Drawing.Size(160, 19);
            this.tbCity.TabIndex = 4;
            this.tbCity.Text = "";
            this.toolTip1.SetToolTip(this.tbCity, "カタカナで入力");
            // 
            // tbTown
            // 
            this.tbTown.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.tbTown.ImeMode = System.Windows.Forms.ImeMode.Katakana;
            this.tbTown.Location = new System.Drawing.Point(104, 88);
            this.tbTown.Name = "tbTown";
            this.tbTown.Size = new System.Drawing.Size(160, 19);
            this.tbTown.TabIndex = 7;
            this.tbTown.Text = "";
            this.toolTip1.SetToolTip(this.tbTown, "カタカナで入力");
            // 
            // cbKen
            // 
            this.cbKen.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.cbKen.Items.AddRange(new object[] {
                                                       "全国",
                                                       "北海道",
                                                       "青森県",
                                                       "岩手県",
                                                       "宮城県",
                                                       "秋田県",
                                                       "山形県",
                                                       "福島県",
                                                       "茨城県",
                                                       "栃木県",
                                                       "群馬県",
                                                       "埼玉県",
                                                       "千葉県",
                                                       "東京都",
                                                       "神奈川県",
                                                       "新潟県",
                                                       "富山県",
                                                       "石川県",
                                                       "福井県",
                                                       "山梨県",
                                                       "長野県",
                                                       "岐阜県",
                                                       "静岡県",
                                                       "愛知県",
                                                       "三重県",
                                                       "滋賀県",
                                                       "京都府",
                                                       "大阪府",
                                                       "兵庫県",
                                                       "奈良県",
                                                       "和歌山県",
                                                       "鳥取県",
                                                       "島根県",
                                                       "岡山県",
                                                       "広島県",
                                                       "山口県",
                                                       "徳島県",
                                                       "香川県",
                                                       "愛媛県",
                                                       "高知県",
                                                       "福岡県",
                                                       "佐賀県",
                                                       "長崎県",
                                                       "熊本県",
                                                       "大分県",
                                                       "宮崎県",
                                                       "鹿児島県",
                                                       "沖縄県"});
            this.cbKen.Location = new System.Drawing.Point(104, 24);
            this.cbKen.MaxDropDownItems = 20;
            this.cbKen.Name = "cbKen";
            this.cbKen.Size = new System.Drawing.Size(88, 20);
            this.cbKen.TabIndex = 1;
            this.cbKen.Text = "全国";
            this.toolTip1.SetToolTip(this.cbKen, "都道府県名を選択");
            // 
            // listBox1
            // 
            this.listBox1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.listBox1.ContextMenu = this.contextMenu1;
            this.listBox1.ItemHeight = 12;
            this.listBox1.Location = new System.Drawing.Point(8, 208);
            this.listBox1.Name = "listBox1";
            this.listBox1.Size = new System.Drawing.Size(368, 184);
            this.listBox1.TabIndex = 3;
            this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
            // 
            // contextMenu1
            // 
            this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                                         this.menuItem3});
            // 
            // menuItem3
            // 
            this.menuItem3.Index = 0;
            this.menuItem3.Shortcut = System.Windows.Forms.Shortcut.CtrlC;
            this.menuItem3.Text = "コピー(&C)";
            this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);
            // 
            // groupBox1
            // 
            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.groupBox1.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                    this.tbZipCode,
                                                                                    this.btnSearchZip,
                                                                                    this.label4});
            this.groupBox1.Location = new System.Drawing.Point(8, 8);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(368, 56);
            this.groupBox1.TabIndex = 1;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "郵便番号より検索";
            // 
            // label4
            // 
            this.label4.Location = new System.Drawing.Point(16, 24);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(56, 16);
            this.label4.TabIndex = 0;
            this.label4.Text = "郵便番号";
            // 
            // groupBox2
            // 
            this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.groupBox2.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                    this.btnClear,
                                                                                    this.label3,
                                                                                    this.label2,
                                                                                    this.label1,
                                                                                    this.tbCity,
                                                                                    this.btnSearchKana,
                                                                                    this.cbKen,
                                                                                    this.tbTown});
            this.groupBox2.Location = new System.Drawing.Point(8, 80);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(368, 120);
            this.groupBox2.TabIndex = 2;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "住所の読みがなより検索";
            // 
            // btnClear
            // 
            this.btnClear.Anchor = (System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right);
            this.btnClear.Location = new System.Drawing.Point(296, 56);
            this.btnClear.Name = "btnClear";
            this.btnClear.Size = new System.Drawing.Size(48, 23);
            this.btnClear.TabIndex = 5;
            this.btnClear.Text = "クリア";
            this.toolTip1.SetToolTip(this.btnClear, "市町村名、町域名をクリアします。");
            this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
            // 
            // label3
            // 
            this.label3.Location = new System.Drawing.Point(8, 88);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(80, 16);
            this.label3.TabIndex = 6;
            this.label3.Text = "町域名(カナ)";
            // 
            // label2
            // 
            this.label2.Location = new System.Drawing.Point(8, 56);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(88, 16);
            this.label2.TabIndex = 3;
            this.label2.Text = "市町村名(カナ)";
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(16, 24);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(56, 16);
            this.label1.TabIndex = 0;
            this.label1.Text = "都道府県";
            // 
            // toolTip1
            // 
            this.toolTip1.AutomaticDelay = 100;
            // 
            // mainMenu1
            // 
            this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                                      this.menuItem1});
            // 
            // menuItem1
            // 
            this.menuItem1.Index = 0;
            this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                                      this.menuItem2});
            this.menuItem1.Text = "ヘルプ(&H)";
            // 
            // menuItem2
            // 
            this.menuItem2.Index = 0;
            this.menuItem2.Text = "バージョン情報(&A)";
            this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);
            // 
            // statusBar1
            // 
            this.statusBar1.Location = new System.Drawing.Point(0, 392);
            this.statusBar1.Name = "statusBar1";
            this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
                                                                                          this.statusBarPanel1});
            this.statusBar1.ShowPanels = true;
            this.statusBar1.Size = new System.Drawing.Size(384, 22);
            this.statusBar1.TabIndex = 0;
            // 
            // statusBarPanel1
            // 
            this.statusBarPanel1.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;
            this.statusBarPanel1.ToolTipText = "Status";
            this.statusBarPanel1.Width = 368;
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(384, 414);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.statusBar1,
                                                                          this.listBox1,
                                                                          this.groupBox1,
                                                                          this.groupBox2});
            this.Menu = this.mainMenu1;
            this.MinimumSize = new System.Drawing.Size(392, 448);
            this.Name = "Form1";
            this.Text = "ZipCode Searcher";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox2.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).EndInit();
            this.ResumeLayout(false);

        }
                #endregion

        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new Form1());
        }

        private ArrayList zipList = null;

        private void btnSearchZip_Click(object sender, System.EventArgs e)
        {
            // エラープロバイダーをクリアする。
            this.errorProvider1.SetError(this.cbKen, "");
            this.errorProvider1.SetError(this.tbCity, "");
            this.errorProvider1.SetError(this.btnSearchKana, "");
            this.errorProvider1.SetError(this.btnSearchZip, "");
            // 現在のカーソルを保存しておく。
            Cursor cursor = this.Cursor;
            // カーソルを WaitCursor にする。
            this.Cursor = Cursors.WaitCursor;
            try
            {
                this.errorProvider1.SetError(this.tbZipCode, "");
                ZipCodeSearcher zipCodeSearcher =
                    new Uchukamen.Util.ZipCodeJapan.ZipCodeSearcher();
                zipList = zipCodeSearcher.GetAddressFromZipCode(this.tbZipCode.Text);
                this.listBox1.Items.Clear();
                this.statusBarPanel1.Text = zipList.Count.ToString() + " 件見つかりました";
                foreach(Uchukamen.Util.ZipCodeJapan.ZipCode zip in zipList)
                {
                    this.listBox1.Items.Add(zip.Code+ "\t" + zip.Ken+zip.City+zip.Town);
                }
            }
            catch (WebException exc)
            {
                this.listBox1.Items.Clear();
                this.statusBarPanel1.Text = exc.Message;
                this.errorProvider1.SetError(this.btnSearchZip, exc.Message);
            }
            catch (Exception exc)
            {
                this.listBox1.Items.Clear();
                this.statusBarPanel1.Text = exc.Message;
                this.errorProvider1.SetError(this.tbZipCode, exc.Message);
            }
            finally
            {
                // カーソルを元に戻す。
                this.Cursor = cursor;
            }
        }

        private void button2_Click(object sender, System.EventArgs e)
        {
            // エラープロバイダーをクリアする。
            this.errorProvider1.SetError(this.cbKen, "");
            this.errorProvider1.SetError(this.tbCity, "");
            this.errorProvider1.SetError(this.btnSearchKana, "");
            this.errorProvider1.SetError(this.btnSearchZip, "");
            // 現在のカーソルを保存しておく。
            Cursor cursor = this.Cursor;
            // カーソルを WaitCursor にする。
            this.Cursor = Cursors.WaitCursor;

            ZipCodeSearcher zipSearcher = 
                new Uchukamen.Util.ZipCodeJapan.ZipCodeSearcher();
            try
            {
                zipList = zipSearcher.GetZipCodeFromAddress(this.cbKen.Text, this.tbCity.Text, this.tbTown.Text);
                this.listBox1.Items.Clear();
                this.statusBarPanel1.Text = zipList.Count.ToString() + " 件見つかりました";
                foreach(Uchukamen.Util.ZipCodeJapan.ZipCode zip in zipList)
                {
                    this.listBox1.Items.Add(zip.Code+ "\t" + zip.Ken+zip.City+zip.Town);
                }
            }
            catch (MultipleKenException exc)
            {
                this.listBox1.Items.Clear();
                string msg = exc.Message;
                foreach(string ken in exc.KenList)
                    msg += "\n" + ken;
                this.statusBarPanel1.Text = msg;
                this.errorProvider1.SetError(this.cbKen, msg);
            }
            catch (WebException exc)
            {
                this.listBox1.Items.Clear();
                this.statusBarPanel1.Text = exc.Message;
                this.errorProvider1.SetError(this.btnSearchKana, exc.Message);
            }
            catch (Exception exc)
            {
                this.listBox1.Items.Clear();
                this.statusBarPanel1.Text = exc.Message;
                this.errorProvider1.SetError(this.tbCity, exc.Message);
            }
            finally
            {
                // カーソルを元に戻す。
                this.Cursor = cursor;
            }
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            this.Icon = new Icon(GetType(), "App.ico"); 
            toolTip1.SetToolTip(this.tbCity, "例:チヨダク、ケセンヌマシ、シラハマチョウなど");
            toolTip1.SetToolTip(this.tbTown, "検索のヒント:町・村を省いたよみがな");
            string defaultKen = ConfigurationSettings.AppSettings["ZipCode.DefaultKen"];
            this.cbKen.Text = defaultKen;
        }

        private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            int i = this.listBox1.SelectedIndex;
            this.cbKen.Text = ((Uchukamen.Util.ZipCodeJapan.ZipCode)zipList[i]).Ken;
            this.tbZipCode.Text = ((Uchukamen.Util.ZipCodeJapan.ZipCode)zipList[i]).Code;
            this.tbCity.Text = ((Uchukamen.Util.ZipCodeJapan.ZipCode)zipList[i]).CityKana;
            this.tbTown.Text = ((Uchukamen.Util.ZipCodeJapan.ZipCode)zipList[i]).TownKana;
        }

        private void btnClear_Click(object sender, System.EventArgs e)
        {        
            this.cbKen.Text = "全国";
            this.tbZipCode.Text = "";
            this.tbCity.Text = "";
            this.tbTown.Text = "";
        }

        private void menuItem2_Click(object sender, System.EventArgs e)
        {
            Form about = new Uchukamen.Util.AboutZipCodeSearcher.About();
            about.ShowDialog();
        }

        private void menuItem3_Click(object sender, System.EventArgs e)
        {
            Clipboard.SetDataObject(this.listBox1.SelectedItem.ToString());
        }
    }
}
ZipCodeUtil.cs
using System;
using System.Collections;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Diagnostics;

namespace Uchukamen.Util.ZipCodeJapan
{    
    #region 複数の県が該当する場合の例外クラス
    /// <summary>
    /// 複数の県が該当する場合の例外クラス
    /// KenList に県のリストをセットする
    /// </summary>
    public class MultipleKenException: Exception
    {
        private ArrayList kenList = new ArrayList();

        public MultipleKenException(string message) : base(message)
        {
        }

        public void Add(string ken)
        {
            kenList.Add(ken);
        }
        
        public ArrayList KenList
        {
            get 
            {
                return kenList; 
            }
        }
    }
    #endregion

    #region 郵便番号クラス
    /// <summary>
    /// 郵便番号クラス
    /// </summary>
    public class ZipCode
    {
        public ZipCode()
        {
        }

        private string code     = "";
        private string ken      = "";
        private string kenKana  = "";
        private string city     = "";
        private string cityKana = "";
        private string town     = "";
        private string townKana = "";

        public string Code
        {
            get 
            {
                return code; 
            }
            set 
            {
                code = value; 
            }
        }

        public string Ken
        {
            get 
            {
                return ken; 
            }
            set 
            {
                ken = value; 
            }
        }

        public string KenKana
        {
            get 
            {
                return kenKana; 
            }
            set 
            {
                kenKana = value; 
            }
        }

        public string City
        {
            get 
            {
                return city; 
            }
            set 
            {
                city = value; 
            }
        }

        public string CityKana
        {
            get 
            {
                return cityKana; 
            }
            set 
            {
                cityKana = value; 
            }
        }

        public string Town
        {
            get 
            {
                return town; 
            }
            set 
            {
                town = value; 
            }
        }

        public string TownKana
        {
            get 
            {
                return townKana; 
            }
            set 
            {
                townKana = value; 
            }
        }

        /// <summary>
        /// 郵便番号で検索した場合のHTMLからセットする。
        /// "<TR><TD> 210-0854<BR>(210  )</TD><TD>カナガワケン<BR>神奈川県</TD>
        /// <TD>カワサキシカワサキク<BR>川崎市川崎区</TD><TD>アサノチョウ<BR>浅野町"
        /// </summary>
        /// <param name="col"></param>
        public void Set1(MatchCollection col)
        {
            // 郵便番号
            if (col.Count > 0) this.Code = col[0].Value;
            // 都道府県名(かな)
            if (col.Count > 1) this.KenKana = col[1].Value;
            // 都道府県名
            if (col.Count > 2) this.Ken = col[2].Value;
            // 市町村名(かな)
            if (col.Count > 3) this.CityKana = col[3].Value;
            // 市町村名
            if (col.Count > 4) this.City = col[4].Value;
            // 町域名(かな)
            if (col.Count > 5) this.TownKana = col[5].Value;
            // 町域名
            if (col.Count > 6) this.Town = col[6].Value;
        }

        /// <summary>
        /// 住所のよみがなで検索した場合のHTMLからセットする。
        /// <TR><TD>210-0854</TD><TD>神奈川県<BR>
        /// <TD>カワサキシカワサキク<BR>川崎市川崎区</TD><TD>アサノチョウ<BR>浅野町</TD></TR>
        /// </summary>
        /// <param name="col"></param>
        public void Set2(MatchCollection col)
        {
            // 郵便番号
            if (col.Count > 0) this.Code = col[0].Value;
            // 都道府県名
            if (col.Count > 1) this.Ken = col[1].Value;
            // 市町村名(かな)
            if (col.Count > 2) this.CityKana = col[2].Value;
            // 市町村名
            if (col.Count > 3) this.City = col[3].Value;
            // 町域名(かな)
            if (col.Count > 4) this.TownKana = col[4].Value;
            // 町域名
            if (col.Count > 5) this.Town = col[5].Value;
        }
        #endregion
    }


    #region ZipCodeSearcher
    /// <summary>
    /// 郵政公社のホームページから、郵便番号・住所を Web 経由で取得する。
    /// 注意: 2003/5/11 時点での検索ページの構成に依存しています。
    ///         このページの構成が変更になると動作しなくなります。
    /// 郵政公社のホームページ http://www.japanpost.jp/
    /// 郵政公社の郵便番号検索ページ http://www.post.japanpost.jp/zipcode/
    /// </summary>
    public class ZipCodeSearcher
    {
        public ZipCodeSearcher()
        {
        }

        private string status = "";
        public string Status
        {
            get 
            {
                return status; 
            }
            set 
            {
                status = value; 
            }
        }

        // 郵便番号→住所のためのURL
        private const string Zip2AddressURL = "http://search.post.japanpost.jp/7zip/zip.cgi";

        // 住所→郵便番号のためのURL(かな検索)
        private const string Address2ZipURL = "http://search.post.japanpost.jp/7zip/kana.cgi";

        /// <summary>
        /// 郵便番号より住所を検索するメソッド
        /// </summary>
        /// <param name="zCode">郵便番号の文字列</param>
        /// <returns>ArrayList of ZipCode Class</returns>
        public ArrayList GetAddressFromZipCode(string zCode)
        {
            System.IO.Stream  stream = null;
            System.IO.StreamReader sr = null;
            ArrayList array = new System.Collections.ArrayList();
            try 
            {
                System.Net.WebRequest webReq = HttpWebRequest.Create( Zip2AddressURL );
                webReq.Method = "POST"; 
                // 1秒でタイムアウトさせる。
                webReq.Timeout = 1000000; 
                // IE のProxy 設定を使用する。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy();
                webReq.ContentType = "application/x-www-form-urlencoded"; 
                // POST パラメータを書く。
                // 正確なパラメータを渡すために HttpUtility.UrlEncode()でエンコードする。
                string parameters = "mode=search&start=0&end=400&keyword=";
                parameters += HttpUtility.UrlEncode(zCode);
                parameters += "&new=on";
                // Ascii なので、エンコーディングは指定する必要なし。
                Stream reqStream = webReq.GetRequestStream();
                StreamWriter sw = new StreamWriter(reqStream);
                sw.Write(parameters);
                sw.Close();
                // 結果を受け取る。
                WebResponse webRes = webReq.GetResponse();
                // HttpWebRequest からストリームを取得する。
                stream = webRes.GetResponseStream();
                // SHIFT JIS で読み取る。
                sr = new StreamReader(stream, Encoding.GetEncoding("SHIFT-JIS"));
                String str = null;
                
                // チェック用正規表現
                Regex regShort = new Regex("(番号が短すぎます)|(新番号の場合は5桁以上入れてください)");
                Regex regHit = new Regex(@"(?<=該当数 \[ )[0-9]+");
                Regex regInfo = new Regex(@"(?<=^<TR><TD> )[0-9]{3}-[0-9]{4}|(?<=<TD>)\w+|(?<=<BR>)\w+");
                
                while( true )
                {
                    str = sr.ReadLine();
                    if (str == null)
                        break;

                    // 番号が短すぎかどうかチェックする。

                    Match matchShort = regShort.Match(str);
                    if (matchShort.Success) 
                    {
                        Debug.WriteLine(matchShort.Value);
                        throw(new Exception(matchShort.Value));
                    }

                    // 検索を成功し、該当数が返されたかチェックする。
                    Match match = regHit.Match(str);
                    if (match.Success) 
                    {
                        Debug.WriteLine("該当数" + match.Value);
                        continue;
                    }
                
                    // 結果から、正規表現を使って住所を切り出す。
                    MatchCollection matchCol = regInfo.Matches(str);
                    if (matchCol.Count > 3)
                    {
                        ZipCode zipCode = new ZipCode();
                        zipCode.Set1(matchCol);
                        array.Add(zipCode);
                        // デバッグ用 
                        Debug.WriteLine(str);
                        for(int i = 0; i < matchCol.Count; i++)
                        {
                            Debug.WriteLine(matchCol[i].Value);
                        }                
                    }
                }            
            } 
            catch (WebException)
            {
                throw(new WebException("郵政公社に接続できませんでした。"));
            }
            finally
            {
                if (sr != null) sr.Close();
                if (stream != null) stream.Close();
            }
            return array;
        }

        /// <summary>
        /// 住所より郵便番号を検索するメソッド
        /// </summary>
        /// <param name="ken">県名</param>
        /// <param name="city">市町村名</param>
        /// <param name="town">町域名</param>
        /// <returns>ArrayList of ZipCode Class</returns>
        public ArrayList GetZipCodeFromAddress(string ken, string city, string town)
        {
            Stream stream = null;
            StreamReader sr = null;
            // 結果用配列
            ArrayList array = new System.Collections.ArrayList();
            try
            {
                WebRequest webReq = HttpWebRequest.Create( Address2ZipURL );
                webReq.Method = "POST"; 
                // 1秒でタイムアウトさせる。
                webReq.Timeout = 1000000; 
                // IE のProxy 設定を使用する。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy();
                webReq.ContentType = "application/x-www-form-urlencoded"; 
                // POST パラメータを書く。
                // 正確なパラメータを渡すために HttpUtility.UrlEncode()でエンコードする。
                string parameters = "enctype=text/plain&ken=";                
                parameters += GetKenCode(ken);
                parameters += "&city=";
                parameters += HttpUtility.UrlEncode(city, Encoding.GetEncoding("SHIFT-JIS"));
                parameters += "&town=";
                parameters += HttpUtility.UrlEncode(town, Encoding.GetEncoding("SHIFT-JIS"));
                StreamWriter sw = new StreamWriter(webReq.GetRequestStream(), Encoding.GetEncoding("SHIFT-JIS"));
                sw.Write(parameters);
                sw.Close();

                WebResponse webRes = webReq.GetResponse();
                // HttpWebRequest からストリームを取得する。
                stream = webRes.GetResponseStream();
                // 1行ごとに扱いたいので、StreamReader にする。
                sr = new System.IO.StreamReader(stream, Encoding.GetEncoding("SHIFT-JIS"));
                String str;

                // チェック用正規表現
                Regex regMultiKen = new Regex("(該当する都道府県が複数あります。)");
                Regex regShort = new Regex("(市区町村名が短がすぎます)|(市区町村名が特定できませんでした。条件をみなおしてみてください)");
                Regex regOp = new Regex("(?<=^<OPTION value=\"[0-9]{2}\">)\\w+$");
                Regex regHit = new Regex(@"(?<=該当数 \[ )[0-9]+");
                Regex regInfo = new Regex(@"(?<=^<TR><TD>)[0-9]{3}-[0-9]{4}|(?<=<TD>)\w+|(?<=<BR>)\w+");

                while( true )
                {
                    str = sr.ReadLine();
                    if (str == null)
                        break;                    
                
                    // 検索を成功し、該当数が返されたかチェックする。
                    Match match = regHit.Match(str);
                    if (match.Success) 
                    {
                        Debug.WriteLine("該当数" + match.Value);
                        this.Status = match.Value;
                    }

                    // 市区町村名が短がすぎかどうかチェックする。
                    Match matchShort = regShort.Match(str);
                    if (matchShort.Success) 
                    {
                        Debug.WriteLine(matchShort.Value);
                        throw(new Exception(matchShort.Value));
                    }

                    // 該当する都道府県が複数あるかどうかチェックする。
                    Match match1 = regMultiKen.Match(str);
                    if (match1.Success) 
                    {
                        status = "該当する都道府県が複数あります。\n";
                        status += "都道府県を指定してください。";
                        MultipleKenException exc = new MultipleKenException(status);
                        Debug.WriteLine(matchShort.Value);
                        while( true )
                        {
                            str = sr.ReadLine();
                            if (str == null)
                                break;
                            Match match2 = regOp.Match(str);
                            if (match2.Success) 
                            {
                                exc.Add(match2.Value);
                                // status +=  " " + match2.Value;
                                Debug.WriteLine(match2.Value);
                            }
                        }
                        throw (exc);
                    }

                    MatchCollection matchCol = regInfo.Matches(str);
                    if (matchCol.Count > 3)
                    {
                        ZipCode zipCode = new ZipCode();
                        zipCode.Set2(matchCol);
                        array.Add(zipCode);
                        // デバッグ用 
                        Debug.WriteLine(str);
                        for(int i = 0; i < matchCol.Count; i++)
                        {
                            Debug.WriteLine(matchCol[i].Value);
                        }                
                    }
                }
            }
            catch (WebException)
            {
                throw(new WebException("郵政公社に接続できませんでした。"));
            }
            finally
            {
                if (sr != null) sr.Close();
                if (stream != null) stream.Close();
            }
            return array;
        }

        /// <summary>
        /// 県名から県のコードを返す。
        /// </summary>
        /// <param name="ken">県名</param>
        /// <returns>県コード</returns>
        private string GetKenCode(string ken)
        {
            switch (ken)
            {
                case "全国":        return "00";
                case "北海道":      return "01";
                case "青森県":      return "02";
                case "岩手県":      return "03";
                case "宮城県":      return "04";
                case "秋田県":      return "05";
                case "山形県":      return "06";
                case "福島県":      return "07";
                case "茨城県":      return "08";
                case "栃木県":      return "09";
                case "群馬県":      return "10";
                case "埼玉県":      return "11";
                case "千葉県":      return "12";
                case "東京都":      return "13";
                case "神奈川県":    return "14";
                case "新潟県":      return "15";
                case "富山県":      return "16";
                case "石川県":      return "17";
                case "福井県":      return "18";
                case "山梨県":      return "19";
                case "長野県":      return "20";
                case "岐阜県":      return "21";
                case "静岡県":      return "22";
                case "愛知県":      return "23";
                case "三重県":      return "24";
                case "滋賀県":      return "25";
                case "京都府":      return "26";
                case "大阪府":      return "27";
                case "兵庫県":      return "28";
                case "奈良県":      return "29";
                case "和歌山県":    return "30";
                case "鳥取県":      return "31";
                case "島根県":      return "32";
                case "岡山県":      return "33";
                case "広島県":      return "34";
                case "山口県":      return "35";
                case "徳島県":      return "36";
                case "香川県":      return "37";
                case "愛媛県":      return "38";
                case "高知県":      return "39";
                case "福岡県":      return "40";
                case "佐賀県":      return "41";
                case "長崎県":      return "42";
                case "熊本県":      return "43";
                case "大分県":      return "44";
                case "宮崎県":      return "45";
                case "鹿児島県":    return "46";
                case "沖縄県":      return "47";
                default:            return "00";
            }
        }
        #endregion
    }
}
about.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace Uchukamen.Util.AboutZipCodeSearcher
{
    /// <summary>
    /// About の概要の説明です。
    /// </summary>
    public class About : System.Windows.Forms.Form
    {
        private System.Windows.Forms.LinkLabel linkLabel1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label2;
        /// <summary>
        /// 必要なデザイナ変数です。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public About()
        {
            //
            // Windows フォーム デザイナ サポートに必要です。
            //
            InitializeComponent();

            //
            // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
            //
        }

        /// <summary>
        /// 使用されているリソースに後処理を実行します。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if(components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

                #region Windows Form Designer generated code
        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            this.linkLabel1 = new System.Windows.Forms.LinkLabel();
            this.label1 = new System.Windows.Forms.Label();
            this.button1 = new System.Windows.Forms.Button();
            this.label2 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // linkLabel1
            // 
            this.linkLabel1.Location = new System.Drawing.Point(80, 80);
            this.linkLabel1.Name = "linkLabel1";
            this.linkLabel1.Size = new System.Drawing.Size(152, 23);
            this.linkLabel1.TabIndex = 0;
            this.linkLabel1.TabStop = true;
            this.linkLabel1.Text = "C# プログラミング";
            this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnLinkClicked);
            // 
            // label1
            // 
            this.label1.Font = new System.Drawing.Font("Arial Black", 20.25F, (System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic), System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.label1.ForeColor = System.Drawing.Color.#AAAAFF;
            this.label1.Location = new System.Drawing.Point(16, 8);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(312, 40);
            this.label1.TabIndex = 1;
            this.label1.Text = "Zip Code Searcher";
            // 
            // button1
            // 
            this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.button1.Location = new System.Drawing.Point(272, 72);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(56, 24);
            this.button1.TabIndex = 2;
            this.button1.Text = "OK";
            // 
            // label2
            // 
            this.label2.Font = new System.Drawing.Font("Arial Black", 12F, (System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic), System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.label2.ForeColor = System.Drawing.Color.#AAAAFF;
            this.label2.Location = new System.Drawing.Point(56, 48);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(199, 28);
            this.label2.TabIndex = 3;
            this.label2.Text = "Ver.1.0    2003/5/18";
            // 
            // About
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(338, 104);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.label2,
                                                                          this.button1,
                                                                          this.label1,
                                                                          this.linkLabel1});
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
            this.Name = "About";
            this.Text = "About";
            this.Load += new System.EventHandler(this.About_Load);
            this.ResumeLayout(false);

        }
                #endregion

        private void About_Load(object sender, System.EventArgs e)
        {
            this.linkLabel1.Links.Add(0, this.linkLabel1.Text.Length,  
                "http://ukamen.hp.infoseek.co.jp/");

        }

        private void OnLinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
        {
            e.Link.Visited = true;
            System.Diagnostics.Process.Start(e.Link.LinkData.ToString());        
        }

    }
}