C# 在javascript操作后获取HtmlDocument

C# 在javascript操作后获取HtmlDocument,c#,javascript,webbrowser-control,dom,C#,Javascript,Webbrowser Control,Dom,在C#中,使用System.Windows.Forms.HtmlDocument类(或另一个允许DOM解析的类),是否可以等到网页完成对HTML的javascript操作后再检索该HTML?某些站点通过javascript将innerhtml添加到页面中,但当我解析HtmlDocument的HtmlElements时,这些更改不会显示出来 一种可能是在一秒钟后更新页面的HtmlDocument。有人知道怎么做吗?使用“WebBrowser.Navigated”事件怎么样?一般来说,答案是“否”-

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


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

使用“WebBrowser.Navigated”事件怎么样?

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

您需要给应用程序一秒钟时间来处理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();
}

我和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();

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

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

我不喜欢这个解决方案,但我认为没有人比它更好

有人重新提出了这个问题,发布了我认为不正确的答案。因此,以下是我的想法来解决这个问题

非决定性的是,很可能会发现页面是否已经完成了AJAX内容。然而,这完全取决于特定页面的逻辑:有些页面是永久动态的

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

完整的样品可以是


我等到导航完成后才获得DOM,但它仍然是过时的DOM。我可以等一秒钟,但如何在一秒钟后获得更新的HTML?WebBrowser对象的HtmlDocument属性仍然是过时的DOM.Body.InnerHtml应该为您提供最新版本的DOM。签出。这如何解决在触发
DocumentCompleted
后所做的DOM更改?
// 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;
}