DOBON.NET DOBON.NETプログラミング掲示板過去ログ

C#でWebRequestを使ってウエブページ内のコンボボックス(select)を選択→HTMLを取得したい

環境/言語:[Windows XP]
分類:[.NET]

下記はHTMLのコンボボックス部分です。WebRequestで1選択〜3選択を選択して各HTMLを取得したいのですが
その方法をご教示頂けないでしょうか。

<select name="target" tabindex="2" onchange="refresh()" style="font-size: 0.85em;">
<option value="1" selected="selected">1選択</option>
<option value="2">2選択</option>
<option value="3">3選択</option></select>

下記のプログラムで試したのですが常にデフォルトの1選択のHTMLしか取得できません。
ネットに公開されているプログラムを真似て作ったものなので処理内容が理解できておらず、何が悪いのか分かりません。

string Html;
TransmitData("Https...", "target&value&2"); //選択をシミュレート(のつもり)
TransmitData("Https...", "onchange=refresh()"); //選択確定をシミュレート(のつもり)
↑ これを実行した後もHtmlには1選択の内容が入っている

private void TransmitData(string s_url, string s_param)
{
httpWebRequest = (HttpWebRequest)WebRequest.Create(s_url);
httpWebRequest.CookieContainer = cookieContainer; //取得済みのクッキーコンテナ
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
byte[] data = Encoding.ASCII.GetBytes(s_param);
httpWebRequest.ContentLength = data.Length;
httpWebRequest.Method = "Post";
Stream reqStream = httpWebRequest.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
WebResponse webResponse = httpWebRequest.GetResponse();
Stream resStream = webResponse.GetResponseStream();
Encoding encoder = Encoding.GetEncoding("Shift_JIS");
StreamReader streamReader = new StreamReader(resStream, encoder);
Html = streamReader.ReadToEnd();
streamReader.Close();
resStream.Close();
}

因みに下記はWebBrowserクラスを使ったプログラムで、こちらは選択したHTMLを取得できていますが、Enterキーの押下をシミュレートしないとデフォルトの1選択となってしまいます。 もっとスマートな方法は無いのでしょうか。

webBrowser1.Document.All.GetElementsByName("target")[0].SetAttribute("value", "2"); //コンボボックス選択
MouseKeyLib.KeyOnSimulate((char)MouseKeyLib.VirtualKeyCodes.VK_ENTER); //Enterキーをシミュレート

【第一希望】WebRequestを使い、バックグランドでHTMLの処理をしたい
【第二希望】WebRequestでの実現が不可能であればWebBrowserでEnterキーをシミュレートすることなく処理したい
2012/09/08(Sat) 23:38:37 編集(投稿者)

■No30907に返信(mark225さんの記事)
> 下記はHTMLのコンボボックス部分です。WebRequestで1選択〜3選択を選択して各HTMLを取得したいのですが
(略)
> <select name="target" tabindex="2" onchange="refresh()" style="font-size: 0.85em;">
> <option value="1" selected="selected">1選択</option>
> <option value="2">2選択</option>
> <option value="3">3選択</option></select>

onchange で JavaScript が動くようですが、あなたが欲しいのはその JavaScript によってもたらされた何かではないのでしょうか?

refresh 関数が何をしているのかわかりませんが、それと同様の内容をあなたが実行する必要があります。
Form パラメーターを書き換えて送信しているのであればそのリクエストを構成する必要があります。それは、その refresh 関数の中身の実装によるので第三者にはアドバイスできません。

もし、refresh 関数が動的に HTML 要素を書き換えているのであれば、HTTP ベースの話ではないので、あなたが JavaScript をパースして実行する仕組みを用意しないといけませんね、WebRequest 路線を続けるのであれば。


WebBrowser で Enter キーが必要というのは、onchage イベントを起こすために必要なのかな?
もしそうであれば、onchange 関数を呼び出せれば良さそうには見えますが…、どういった方法があったか失念。

// Uri = new Uri("javascript:onchange()"); とかでいけるんだろうか?自信なし。
早速の回答を頂き、有り難うございます。
返信が遅れましてすみません。

頂いた回答を基に自分なりに調べながら試してみたのですがやはり分からないのでもう少しお付き合い頂けないでしょうか。

> もし、refresh 関数が動的に HTML 要素を書き換えているのであれば、HTTP ベースの話ではないので、あなたが JavaScript をパースして実行する仕組みを用意しないといけませんね、WebRequest 路線を続けるのであれば。
>
ご指摘頂いたところは下記のとおりです。
function refresh() {
document.optionPriceListForm.action = 'https...';
document.optionPriceListForm.submit();
}
無知な私には単にURLを送信している様にしか見えませんので、試しにTransmitData("https...", "https...")を送ってみたのですが結果は同じでした。
理解できていないので的外れなことをしている気もするのですが、とうすれば良いのかお教え頂けないでしょうか。

> // Uri = new Uri("javascript:onchange()"); とかでいけるんだろうか?自信なし。
>
Uri()メソッド自体が初めてで、何をするメソッドかも知りませんでしたので調べてみたのですが未だ分かっていません。 引き続き更に調べますが…。

取り敢えず、Enterキーシミュレートの替わりに
Uri uri = new Uri("javascript:onchange()");
を入れて試しましたが症状的にはこれが無いのと同じでした。

このメソッドの使い方が正しいと仮定した場合、uriを使って更なる処理が必要なのでしょうか。 その辺り、もう少し突っ込んで教えて頂けると有難いです。
2012/09/09(Sun) 12:47:34 編集(投稿者)

■No30909に返信(mark225さんの記事)
> 無知な私には単にURLを送信している様にしか見えませんので、

少し違います。
その URL に対して、フォームの内容を送信しているのでそのフォームで指定されている method を使って、input で指定されているパラメーターを送る必要があります。
何が必要かは optionPriceListForm の名前がついている form タグ内の input タグを調べてください。


> 理解できていないので的外れなことをしている気もするのですが、とうすれば良いのかお教え頂けないでしょうか。

HTML フォームとそれを送信する際の HTTP の通信の関係を知る必要があると思います。
それがわからないのであれば、HttpWebRequest ベースでは作れません。

フォームにあるテキスト入力フィールドがどうやってサーバーに送られているのか、そのあたりをまずは知ってください。

ヒント
<form method="POST" action="...">
<input type="hidden" name="hoge" value="aaaa">
<input type="hidden" name="foo" value="bbbb">
</form>

これなら action に対して、hoge=aaaa&foo=bbbb という内容を POST で送らないとダメですね。
method が GET なら URL の末尾につける必要があります。


> 取り敢えず、Enterキーシミュレートの替わりに
> Uri uri = new Uri("javascript:onchange()");
> を入れて試しましたが症状的にはこれが無いのと同じでした。

私がちらっと書いた内容が悪かったとは思いますが、単なる変数に入れるだけでは何も起きないというのは気づいて欲しいです。

WebBrowser に何かさせるには WebBrowser に対する操作が必要です。
具体的に書いて欲しいという気持ちもわかりますが、私が試せていないのできちんと書いていません。(コメント形式で書いていたのはそういう意味を込めています)

申し訳ないですが、こちらの方法を探るのであれば、WebBrowser に JavaScript を実行させる方法を自分で調べてみてもらえますか。

追記
「WebBrowser JavaScript」などで少し調べた結果、こういったものがあることがわかったので追記しておきます。具体的なやり方を聞くだけでなく、キーワードから調べてみると言うことも挑戦しましょう。
http://msdn.microsoft.com/ja-jp/library/be9zzz62(v=vs.80)
迅速な回答、有り難うございます。

> フォームにあるテキスト入力フィールドがどうやってサーバーに送られているのか、そのあたりをまずは知ってください。
>
はい、勉強します。

> ヒント
> <form method="POST" action="...">
> <input type="hidden" name="hoge" value="aaaa">
> <input type="hidden" name="foo" value="bbbb">
> </form>
>
> これなら action に対して、hoge=aaaa&foo=bbbb という内容を POST で送らないとダメですね。
> method が GET なら URL の末尾につける必要があります。
>
ご指摘部分は下記の様な感じになっていました。
<form name="optionPriceListForm" id="optionPriceListForm" method="post" action="https...">
<div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="2644e..."></div>
<input type="hidden" name="display" value="1" id="display">
それで、
TransmitData("Https...", "target&value&2&org.apache.struts.taglib.html.TOKEN=2644e...&display=1");
と、してみたのですが結果は同じでした。(method="post"となっています)
回答に「ヒント」とありますので単にこれだけでは駄目なのでしょうか。
奥が深そうですがお教え頂いたキーワードをもっと調べてみます。

> 申し訳ないですが、こちらの方法を探るのであれば、WebBrowser に JavaScript を実行させる方法を自分で調べてみてもらえますか。
>
> 追記
> 「WebBrowser JavaScript」などで少し調べた結果、こういったものがあることがわかったので追記しておきます。具体的なやり方を聞くだけでなく、キーワードから調べてみると言うことも挑戦しましょう。
> http://msdn.microsoft.com/ja-jp/l
>
ご親切に有り難うございます。
お教え頂いたURLの内容は私には難解ですが、取り敢えず「第一希望」のWebRequestを使った方法から攻めていきたいと思います。
2012/09/09(Sun) 16:29:28 編集(投稿者)

■No30911に返信(mark225さんの記事)
> ご指摘部分は下記の様な感じになっていました。
> <form name="optionPriceListForm" id="optionPriceListForm" method="post" action="https...">
(略
> ("Https...", "target&value&2&org.apache.struts.taglib.html.TOKEN=2644e...&display=1");
> と、してみたのですが

target&value&2& ってなんでしょうか?
もしかして、コンボボックス(select タグ)に当てはめるために書いたものですか?

POST/GET で扱うフォームのパラメーターは キー1=値1&キー2=値2&...&キーn=値n という構造になるだけなので、その書式に沿っていない以上はうまくいきません。


あと、自分が作ったリクエストとブラウザのリクエストが違うのであれば、 Fiddler などのツールを使って、どのようなリクエストが飛んでいるか見るのも一手でしょうね。
度々迅速な回答、有り難うございます。

> target&value&2& ってなんでしょうか?
> もしかして、コンボボックス(select タグ)に当てはめるために書いたものですか?
>
> POST/GET で扱うフォームのパラメーターは キー1=値1&キー2=値2&...&キーn=値n という構造になるだけなので、その書式に沿っていない以上はうまくいきません。
>
処理内容が理解できずに暗中模索状態でしたのでこの様なピンポイントでのご指摘、大変助かりました。

ご指摘頂いて、
TransmitData("Https...", "target=2&org.apache.struts.taglib.html.TOKEN=2644e...&display=1");
と、したところ期待通りのHTMLを受信することができました。

今迄ネットを漁りまくっていたのですが解決の糸口が掴めず、曇り空だったのが一気に快晴になった気分です。

無知な私に最後までお付き合い頂き、本当に有り難うございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板