トップ回答者
WebBrowserを使ったJSPページのOuterHtml取得について

質問
-
WebBrowser上でオブジェクトのOuterHtmlを取得しています。
WebBrowserでNavigateをしてNavigate処理が終わった時点に
取得したHtmlElementのOuterHtmlとその後、WebBrowser上のオブジェクトをクリックして
取得したHtmlElementのOuterHtmlを比べましたが、同じオブジェクトなのにOuterHtmlの値が違います。
以下は簡単なサンプルコードです。
using System; using System.Windows.Forms; namespace OuterHtmlTest { public partial class Form1 : Form { private string urlToNavi = "http://www.ae.com"; public Form1() { InitializeComponent(); webBrowser1.Size = new System.Drawing.Size(455, 105); this.Load += new EventHandler(Form1_Load); } void Form1_Load(object sender, EventArgs e) { // 起動時に該当サイトへのナビ webBrowser1.Navigate(urlToNavi); } private void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e) { if (e.Url == webBrowser1.Url) { // ナビ許容禁止 webBrowser1.AllowNavigation = false; // WebBrowser上のクリックイベント登録 webBrowser1.Document.Click += new HtmlElementEventHandler(Document_Click); // ナビが終わった直後のHtmlElement取得 HtmlElement elem = webBrowser1.Document.All[75] as HtmlElement; MessageBox.Show("ナビが終わった直後のOuterHtml(American Eagle Outfitters)" +
Environment.NewLine + elem.OuterHtml); } } void Document_Click(object sender, HtmlElementEventArgs e) { // WebBrowser上でクリックされたところのHtmlElement取得 HtmlElement elem = webBrowser1.Document.GetElementFromPoint(e.ClientMousePosition); MessageBox.Show("画面上のオブジェクトをクリックしたときのOuterHtml" +
Environment.NewLine + elem.OuterHtml); } } }サンプルコードを動かすとWebBrowserの真ん中に
American Eagle Outfittersというタイトルが表示されて、
そのオブジェクトについてのOuterHtmlがMessageBoxとして表示されます。このときのOuterHtml値は以下のようです。
<A href="http://www.ae.com/web/index.jsp">American Eagle Outfitters</A>
それから、WebBrowser上でAmerican Eagle Outfittersタイトルをクリックして
OuterHtmlを出力してみると、以下のような値が取得されます。<A href="http://www.ae.com/web/index.jsp" s_oid="http://www.ae.com/web/index.jsp" s_oidt="0">American Eagle Outfitters</A>
違いとしてはナビの終わった時点のOuterHtmlには
s_oid, s_oidtという(自作の?)Attributeが入ってないことです。希望としてはナビの終わった時点で、
自作Attributeの入っているOuterHtmlを取得したいと思いますが、
WebBrowser.Document.Allから取得するのが間違っているのでしょうか?ちなみに、JSP以外のサイトページでは
両方同じOuterHtmlの値が取得できましたので、
今の段階ではJSPページが原因だと思います。何卒、ご教授よろしくお願いします。
回答
-
追加です。
webBrowser1.Document.All[75] で HtmlElement を取得した後でも、それをプログラムでクリックしてか
ら OuterHtml を取得すれば s_oid, s_oidt が追加されます。具体的には以下のようにします。
HtmlElement elem = webBrowser1.Document.All[75] as HtmlElement;
elem.InvokeMember("click"); // この行を追加する
MessageBox.Show("ナビが終わった直後のOuterHtml(American Eagle Outfitters)" +
Environment.NewLine + elem.OuterHtml);- 回答としてマーク tristan28 2009年10月15日 15:51
すべての返信
-
Hongliangさん。
ご回答、ありがとうございます。
教えて頂いた方法を参考にして、
以下のように処理を追加してみました。
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { if (e.Url == webBrowser1.Url) { // ナビ許容禁止 webBrowser1.AllowNavigation = false; // WebBrowser上のクリックイベント登録 webBrowser1.Document.Click += new HtmlElementEventHandler(Document_Click); Application.Idle += new EventHandler(Application_Idle); } } void Application_Idle(object sender, EventArgs e) { // ナビが終わった直後のHtmlElement取得 HtmlElement elem = webBrowser1.Document.All[75] as HtmlElement; MessageBox.Show("ナビが終わった直後のOuterHtml(American Eagle Outfitters)" + Environment.NewLine + elem.OuterHtml); }
一応、テストしてみましたが、
自作のAttributeは取れませんでした。
取得するタイミングをもうちょっと遅らせる必要があるのでしょうか? -
Hongliangさん。
ご回答、ありがとうございます。
>タイマを使って取れなければいくらか待って再試行
教えて頂いた方法を参考にして試してみました。
タイマを使って5秒置きで何分間Document.Allで取得してみましたが、
結局、問題のAttribute(s_oid, s_oidt)は取れませんでした。
そこで一つ質問させて頂きたいと思いますが、
Document.All以外に別のメソッド、プロパティなどを使って
HtmlElementを取得する方法はないのでしょうか?
WebBrowser上をクリックしてHtmlElement取得する場合、
Document.GetElementFromPoint()を使えば例のAttributeまで全部取れるので、
それに相応しているメソッド/プロパティがあるのではないかと思います。
一応、Documentのメンバーを調べてみましたが、
いけそうなメンバーは見つけませんでした。 (_ _);
度々質問ばかりで恐縮ですが、
ご教授よろしくお願い致します。 -
s_oid, s_oidt が現れたり消えたりするのは、OMNITURE 社の Web アクセス解析ツール
SiteCatalyst(下記 Web Site 参照)の仕業と思います。OMNITURE SiteCatalyst
http://www.sitecatalyst.jp/上記サイトによると、「サイトカタリストは、WEBサイトに埋め込まれたスクリプト(JavaScript)
がアクセス情報を認識することで解析を実行するタグ型のWEBサイト分析ソリューションで
す。」とのことです。問題のページにも、以下のように SiteCatalyst 関係のスクリプトが埋め込まれており、
s_code.js の中に s_oid, s_oidt が存在します。<!-- START OF Omniture Code -->
<!-- SiteCatalyst code version: H.20.3.
Copyright 1997-2009 Omniture, Inc. More info available at
http://www.omniture.com -->
<script type="text/javascript"
src="/web/javascript/omniture/s_code.js"></script>
・・・以下、省略・・・という訳で、Hongliang さんが回答されているとおり、「クリックしたから」が正解だと思います。
(「クリック」=「アクセス」ということで、アクセス情報取得のため s_oid, s_oidt が JavaScript
によって追加されるのだと思います)要するに、
(1) もともとの HtmlElement には s_oid、s_oidt は含まれていない。
(2) クリックした時 JavaScript がアクセス情報として s_oid、s_oidt を追加する。
(3) Document.All とか Document.GetElementById はアクセスとは判断されず、
s_oid、s_oidt は追加されない。ということだと思います。
s_code.js を解析すれば、何故クリックしたら s_oid, s_oidt が現れるのか明確になるかもしれま
せん。(実際、とてもそこまでやってられないと思いますが) -
追加です。
webBrowser1.Document.All[75] で HtmlElement を取得した後でも、それをプログラムでクリックしてか
ら OuterHtml を取得すれば s_oid, s_oidt が追加されます。具体的には以下のようにします。
HtmlElement elem = webBrowser1.Document.All[75] as HtmlElement;
elem.InvokeMember("click"); // この行を追加する
MessageBox.Show("ナビが終わった直後のOuterHtml(American Eagle Outfitters)" +
Environment.NewLine + elem.OuterHtml);- 回答としてマーク tristan28 2009年10月15日 15:51
-
SuferOnWwwさん。
毎度、ご回答ありがとうございます。
素晴らしい情報収集能力と親切な説明に感動しちゃいました。(笑)お蔭様で問題になってた原因と
勘違いしてたところがはっきり分かりました。教えて頂いたとおりに
取得したHtmlElementに対して"click"Invoke処理をかけたら
今まで隠れてた?s_oid, s_oidt Attributeが取れました!!この問題に時間を割愛してくださった皆様、
誠にありがとうございました!! <(_ _)>
・
・
あ、ちなみにSuferOnWwwさん。この件とは関係ない話ですが、
一応、情報共有のために書きます。
複数のFrameで構成されたサイトページのNavigate処理について
DocumentCompletedが最終的に呼び出されるタイミングを捕捉するためには
以下のような3つの判定方法があるようです。
宜しければご参考にしてください。f(^^;)private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { // ナビ処理完了を判定 if (webBrowser1.ReadyState == WebBrowserReadyState.Complete) if (!webBrowser1.IsBusy) if (e.Url.AbsoluteUri == webBrowser1.Url.AbsoluteUri) { // 処理内容 } }