簡體   English   中英

javascript操作后獲取HtmlDocument

[英]Get HtmlDocument after javascript manipulations

在 C# 中,使用 System.Windows.Forms.HtmlDocument 類(或另一個允許 DOM 解析的類),是否可以等到網頁完成對 HTML 的 javascript 操作后再檢索該 HTML? 某些站點通過 javascript 將 innerhtml 添加到頁面,但是當我解析 HtmlDocument 的 HtmlElements 時,這些更改不會顯示。

一種可能性是在一秒鍾后更新頁面的 HtmlDocument。 有人知道怎么做這個嗎?

有人通過發布我認為不正確的答案來重新提出這個問題。 所以,這里是我的想法來解決它。

非確定性地,有可能接近找出頁面是否已完成其 AJAX 內容。 但是,這完全取決於該特定頁面的邏輯:有些頁面是永久動態的。

為了解決這個問題,可以先處理DocumentCompleted事件,然后異步輪詢WebBrowser.IsBusy屬性並監視頁面的當前 HTML 快照以進行更改,如下所示。

可以在此處找到完整的示例。

// 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;
}

一般來說,aswer 是“否” - 除非頁面上的腳本以某種方式通知您的代碼,否則您必須等待一段時間並獲取 HTML。 在文檔就緒通知之后等待一秒鍾,可能會覆蓋大多數站點(即 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();

    }

如果您嘗試在控制台應用程序中執行此操作,則需要將此標記放在 main 上方,因為 Windows 需要與 COM 組件進行通信:

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

我不喜歡這個解決方案,但我認為沒有人更好!

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM