none
Webページの内容を取得 RRS feed

  • 質問

  • msdn
    いつもお世話になります。
    Windows7 VisualStudio2010での開発で質問です。
    Webブラウザコントロールを使って、Webページにアクセスし、その内容を取得しようとしています。

    private string webresult(){
    webBrowser1.Navigate("http://www.google.co.jp/");
    do { Application.DoEvents(); } while (webBrowser1.ReadyState != WebBrowserReadyState.Complete || webBrowser1.IsBusy == true);
    HtmlElementCollection inputs = webBrowser1.Document.All.GetElementsByName("q");
    //テキストボックスにkeywordをセット。
    inputs[0].SetAttribute("value", "C#検索テスト");
    HtmlElementCollection buttons = webBrowser1.Document.GetElementsByTagName("button");
    buttons[0].InvokeMember("click");
    //結果ページにアクセスするのを待つ。
    do { Application.DoEvents(); } while (webBrowser1.ReadyState != WebBrowserReadyState.Complete || webBrowser1.IsBusy == true);
    //結果を取得しているつもり。
    string result = webBrowser1.DocumentText;
    return result;
    }

    というものです。
    これで、resultを取得すると、結果ページではなく、最初のページの内容を取得しています。
    結果ページのテキストを取得するには、どのようにしたらよいのでしょう?

    これはメソッドで、結果を別のメソッドに結果を返す必要があるので、DocumentCompleteでというのでしたら、そちらから呼び出したメソッドに結果を返す方法をご示唆いただけるとうれしいです。

     

    2013年3月14日 10:40

回答

  • > DocumentCompletedを使うとしたら、どのようにしたらよいのでしょう?

    質問に書かれているような mainMethod と webresult という 2 つのメソッドを使うという構造にこだわらないで、以下のような手順をコーディングすれば可能と思います。

    (1) WebBrowser を初期画面に Navigate する。

    (2) DocumentCompleted イベントが発生。

    (3) イベントハンドラで初期画面か次画面かを判断。

    (4) 初期画面であれば、必要な処置をして次画面に Navigate(最初の質問の例ではテキストボックスに keyword をセットしてボタンクリック)。

    (5) DocumentCompleted イベントが発生。

    (6) イベントハンドラ(上記 (3) と同じもの)で初期画面か次画面かを判断。

    (7) 次画面であればその内容を取得する。

    2013年3月16日 11:06

すべての返信

  • > 結果ページのテキストを取得するには、どのようにしたらよいのでしょう?

    google はダメなようです。

    以下のスレッドと同じ話だと思いますが、どうもそういうことをさせないような仕組みになっているように見えます。

    WebBrowserでHTML要素のclick処理について
    http://social.msdn.microsoft.com/Forums/en-US/netfxgeneralja/thread/55e5478b-c636-41d9-b69b-5799022396f8

    ブラウザ (IE) を手動で操作し、開発者ツールで、初期画面と検索後画面の HTML ソースを見比べてください。同じになっているはずです。 表示が違うのは JavaScript で何かやっているからだと思います。

    #上に紹介したスレッドにも書きましたが、Application.DoEvents メソッドをループに入れて使うのは止めた方がいいと思います。

    2013年3月15日 11:58
  • 件のページではHTML5 History APIを使用していて、JavaScriptからページ遷移したかのように見せかけ、表示内容を全て制御しています。
    実際にはページ遷移していないわけですから、ReadyStateやIsBusyなどを監視しても変化していないかもしれません。

    Googleとしては画面表示ではなく、Custom Search APIを使い検索結果のデータを取得することを推奨しているはずです。

    2013年3月16日 0:52

  • SurferOnWwwさん。
    コメントありがとうございます。
    ご示唆いただいたページも拝見しました。

    Application.DoEventsではなくて、DocumentCompletedを使うほうがベターだとは思っているのですが、今回のは、あるメソッドからこのメソッド(webresult)を呼び出し、結果をそのもとのメソッドに返す必要があるのです。

    もしこういう場合に、DocumentCompletedを使うとしたら、どのようにしたらよいのでしょう?

    private void mainMethod(){
     string result = webresult();
     //resultの値によって処理。

    }

    private string webresult(){
     string result;

     return result;
    }

    という構造です。
    ここに、DocumentCompletedがはいると、

    private void mainMethod(){
     //resultの値によって処理を分けたいが…。

    }

    private void webresult(){
     //ここでは結果がでないので、結果の処理ができない。
    }

    private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
     string result;

     return result;
    }

    となって、構造をどのようにしたらよいか、よくわかりません。
    そちらをご助言いただけるとうれしいです。

    なお、Googleを例にしたのは一般論のためで、あまり適切でなかったようです。
    Googleにこだわらず、ご回答いただければ幸いです。

     

    2013年3月16日 8:19
  • 佐祐理さん。
    コメントありがとうございます。

    Googleを例にしたのは一般論のためで、あまり適切でなかったようです。
    Googleにこだわらず、ご回答いただければ幸いです。

     

    2013年3月16日 8:20
  • > DocumentCompletedを使うとしたら、どのようにしたらよいのでしょう?

    質問に書かれているような mainMethod と webresult という 2 つのメソッドを使うという構造にこだわらないで、以下のような手順をコーディングすれば可能と思います。

    (1) WebBrowser を初期画面に Navigate する。

    (2) DocumentCompleted イベントが発生。

    (3) イベントハンドラで初期画面か次画面かを判断。

    (4) 初期画面であれば、必要な処置をして次画面に Navigate(最初の質問の例ではテキストボックスに keyword をセットしてボタンクリック)。

    (5) DocumentCompleted イベントが発生。

    (6) イベントハンドラ(上記 (3) と同じもの)で初期画面か次画面かを判断。

    (7) 次画面であればその内容を取得する。

    2013年3月16日 11:06
  • Googleにこだわっているのはどちらでしょう?

    Googleのような最新技術を使いまくるサイトだからこそ取得できないのであって、古いサイトなどであればキャットリリスさんの書かれた方法で取得できるのではないでしょうか。
    最新技術を使うサイトにも対応するためには、質問者さん自身も最新技術を知り、それに対応する必要がある、それだけのことです。

    2013年3月16日 23:03
  • SurferOnWwwさん
    コメントありがとうございます。

    このふたつのメソッドの構造は、特にこだわりがありません。
    最初の質問で、
    「結果を別のメソッドに結果を返す必要があるので、DocumentCompleteで」というのもオーケーと書いたとおりです。

    ただ、この(1)~(7)の場合では、値を元のメソッドに返すことができないのではないか、と思います。
    そこで、ここはフィールドの併用などで逃げることにしました。

    ありがとうございました。

    2013年3月20日 11:34