【问题标题】:Get HtmlDocument after javascript manipulationsjavascript操作后获取HtmlDocument
【发布时间】:2011-12-07 02:40:48
【问题描述】:

在 C# 中,使用 System.Windows.Forms.HtmlDocument 类(或其他允许解析 DOM 的类),是否可以等到网页完成其对 HTML 的 javascript 操作后再检索该 HTML?某些网站通过 javascript 将 innerhtml 添加到页面中,但是当我解析 HtmlDocument 的 HtmlElements 时,这些更改并未显示出来。

一种可能性是在一秒钟后更新页面的 HtmlDocument。有人知道怎么做吗?

【问题讨论】:

    标签: c# javascript webbrowser-control dom


    【解决方案1】:

    使用 'WebBrowser.Navigated' 事件怎么样?

    【讨论】:

    • 我等到导航完成才获取 DOM,但它仍然是过时的 DOM。
    【解决方案2】:

    通常回答是“否”——除非页面上的脚本以某种方式通知您的代码,否则您必须等待一段时间并获取 HTML。在文档就绪通知之后等待一秒钟,likley 将覆盖大多数网站(即 jQuery 的 $(code) 案例)。

    【讨论】:

    • 我可以等待一秒钟,但是如何在一秒钟后获得更新的 HTML? WebBrowser 对象的 HtmlDocument 属性仍然是过时的 DOM。
    • Body.InnerHtml 应该为您提供最新版本的 DOM。查看msdn.microsoft.com/en-us/library/ms171712.aspx
    【解决方案3】:

    您需要给应用程序一点时间来处理 Java。简单地停止当前线程也会延迟 java 处理,因此您的文档仍然会过时。

    WebBrowserDocumentCompletedEventArgs cachedLoadArgs;
    
    private void TimerDone(object sender, EventArgs e)
    {
        ((Timer)sender).Stop();
        respondToPageLoaded(cachedLoadArgs);
    }
    
    void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        cachedLoadArgs = e;
    
        System.Windows.Forms.Timer timer = new Timer();
    
        int interval = 1000;
    
        timer.Interval = interval;
        timer.Tick += new EventHandler(TimerDone);
        timer.Start();
    }
    

    【讨论】:

      【解决方案4】:

      我用 WEBBrowser 做的看看我的课:

      public class MYCLASSProduct: IProduct
      {
          public string Name { get; set; }
          public double Price { get; set; }
          public string Url { get; set; }
      
          private WebBrowser _WebBrowser;
          private AutoResetEvent _lock;
      
          public void Load(string url)
          {
              _lock = new AutoResetEvent(false);
              this.Url = url;
      
              browserInitializeBecauseJavascriptLoadThePage();
          }
      
          private void browserInitializeBecauseJavascriptLoadThePage()
          {
              _WebBrowser = new WebBrowser();
              _WebBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
              _WebBrowser.Dock = DockStyle.Fill;
              _WebBrowser.Name = "webBrowser";
              _WebBrowser.ScrollBarsEnabled = false;
              _WebBrowser.TabIndex = 0;
              _WebBrowser.Navigate(Url);
      
              Form form = new Form();
              form.Hide();
              form.Controls.Add(_WebBrowser);
      
              Application.Run(form);
              _lock.WaitOne();
          }
      
          private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
          {
              HtmlAgilityPack.HtmlDocument hDocument = new HtmlAgilityPack.HtmlDocument();
              hDocument.LoadHtml(_WebBrowser.Document.Body.OuterHtml);
              this.Price = Convert.ToDouble(hDocument.DocumentNode.SelectNodes("//td[@class='ask']").FirstOrDefault().InnerText.Trim());
              _WebBrowser.FindForm().Close();
              _lock.Set();
      
          }
      

      如果您尝试在控制台应用程序中执行此操作,则需要将此标记放在 main 上方,因为 Windows 需要与 COM 组件通信:

      [STAThread]
          static void Main(string[] args)
      

      我不喜欢这个解决方案,但我认为没有比这更好的了!

      【讨论】:

      • 如何解决 DocumentCompleted 被触发后所做的 DOM 更改?
      【解决方案5】:

      有人通过发布我认为不正确的答案重新提出了这个问题。所以,这里是我的想法来解决它。

      在不确定的情况下,可以接近找出页面是否已完成其 AJAX 内容。但是,这完全取决于该特定页面的逻辑:某些页面是永久动态的。

      要解决这个问题,可以先处理 DocumentCompleted 事件,然后异步轮询 WebBrowser.IsBusy 属性并监视页面的当前 HTML 快照是否有更改,如下所示。

      完整的示例可以是found here

      // get the root element
      var documentElement = this.webBrowser.Document.GetElementsByTagName("html")[0];
      
      // poll the current HTML for changes asynchronosly
      var html = documentElement.OuterHtml;
      while (true)
      {
          // wait asynchronously, this will throw if cancellation requested
          await Task.Delay(500, token); 
      
          // continue polling if the WebBrowser is still busy
          if (this.webBrowser.IsBusy)
              continue; 
      
          var htmlNow = documentElement.OuterHtml;
          if (html == htmlNow)
              break; // no changes detected, end the poll loop
      
          html = htmlNow;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-22
        • 2021-08-22
        • 1970-01-01
        • 2021-06-29
        • 2015-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多