首页  >  文章  >  web前端  >  如何不受限制地使用 .NET 检索动态生成的 HTML 代码?

如何不受限制地使用 .NET 检索动态生成的 HTML 代码?

Linda Hamilton
Linda Hamilton原创
2024-10-18 08:40:03851浏览

How to Retrieve Dynamically Generated HTML Code Using .NET without Limitations?

如何使用.NET的WebBrowser或mshtml.HTMLDocument动态生成HTML代码?

简介

动态检索HTML代码网页生成是网络自动化和抓取场景中的常见任务。 .NET 提供了两个选项来实现此目的:System.Windows.Forms.WebBrowser 类和 mshtml.HTMLDocument 接口。然而,有效地使用它们可能具有挑战性。

WebBrowser 类

System.Windows.Forms.WebBrowser 类旨在将网页嵌入到应用程序中。虽然它支持自定义导航和文档事件,但捕获动态生成的 HTML 的能力有限。

以下代码片段说明了如何使用 WebBrowser:

<code class="csharp">using System.Windows.Forms;
using mshtml;

namespace WebBrowserTest
{
    public class Program
    {
        public static void Main()
        {
            WebBrowser wb = new WebBrowser();
            wb.Navigate("https://www.google.com/#q=where+am+i");

            wb.DocumentCompleted += delegate(object sender, WebBrowserDocumentCompletedEventArgs e)
            {
                mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)wb.Document.DomDocument;
                foreach (IHTMLElement element in doc.all)
                {
                    System.Diagnostics.Debug.WriteLine(element.outerHTML);
                }
            };
            Form f = new Form();
            f.Controls.Add(wb);
            Application.Run(f);
        }
    }
}</code>

mshtml.HTMLDocument接口

mshtml.HTMLDocument 接口提供对底层 HTML 文档对象的直接访问。但是,它需要手动导航和渲染,这使得动态生成内容不太方便。

以下代码片段说明了如何使用 mshtml.HTMLDocument:

<code class="csharp">using mshtml;

namespace HTMLDocumentTest
{
    public class Program
    {
        public static void Main()
        {
            mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)new mshtml.HTMLDocument();
            doc.write(new System.Net.WebClient().DownloadString("https://www.google.com/#q=where+am+i"));

            foreach (IHTMLElement e in doc.all)
            {
                System.Diagnostics.Debug.WriteLine(e.outerHTML);
            }
        }
    }
}</code>

更强大的方法

要克服 WebBrowser 和 mshtml.HTMLDocument 的限制,您可以使用以下方法:

  1. 创建 WebBrowser 控件。
  2. 导航到目标 URL 并处理 DocumentCompleted 事件以获取底层 mshtml.HTMLDocument2 对象。
  3. 结合使用轮询和检查 WebBrowser.IsBusy 来检测页面何时完成渲染。
  4. 获取根元素并轮询其 OuterHtml 属性,直到其变得稳定。

示例代码

以下 C# 代码演示了此方法:

<code class="csharp">using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using mshtml;

namespace DynamicHTMLFetcher
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            this.webBrowser.DocumentCompleted += WebBrowser_DocumentCompleted;
            this.Load += MainForm_Load;
        }

        private async void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                var cts = new CancellationTokenSource(10000); // cancel in 10s
                var html = await LoadDynamicPage("https://www.google.com/#q=where+am+i", cts.Token);
                MessageBox.Show(html.Substring(0, 1024) + "..."); // it's too long!
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private async Task<string> LoadDynamicPage(string url, CancellationToken token)
        {
            var tcs = new TaskCompletionSource<bool>();
            WebBrowserDocumentCompletedEventHandler handler = (s, arg) => tcs.TrySetResult(true);

            using (token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: true))
            {
                this.webBrowser.DocumentCompleted += handler;
                try
                {
                    this.webBrowser.Navigate(url);
                    await tcs.Task; // wait for DocumentCompleted
                }
                finally
                {
                    this.webBrowser.DocumentCompleted -= handler;
                }
            }

            var documentElement = this.webBrowser.Document.GetElementsByTagName("html")[0];
            var html = documentElement.OuterHtml;
            while (true)
            {
                await Task.Delay(500, token);
                if (this.webBrowser.IsBusy)
                    continue;
                var htmlNow = documentElement.OuterHtml;
                if (html == htmlNow)
                    break; // no changes detected, end the poll loop
                html = htmlNow;
            }

            token.ThrowIfCancellationRequested();
            return html;
        }

        private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Intentional no-op handler, we receive the DocumentCompleted event in the calling method.
        }
    }
}</code>

此方法可确保您获得完全呈现的 HTML 代码,即使它是动态生成的。

以上是如何不受限制地使用 .NET 检索动态生成的 HTML 代码?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn