Maison  >  Article  >  interface Web  >  Comment récupérer du code HTML généré dynamiquement à l'aide de .NET sans limitations ?

Comment récupérer du code HTML généré dynamiquement à l'aide de .NET sans limitations ?

Linda Hamilton
Linda Hamiltonoriginal
2024-10-18 08:40:03851parcourir

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

Comment générer dynamiquement du code HTML à l'aide du navigateur Web .NET ou de mshtml.HTMLDocument ?

Introduction

Récupération dynamique du code HTML générés par les pages Web est une tâche courante dans les scénarios d’automatisation et de scraping Web. .NET propose deux options pour y parvenir : la classe System.Windows.Forms.WebBrowser et l'interface mshtml.HTMLDocument. Cependant, les utiliser efficacement peut être difficile.

La classe WebBrowser

La classe System.Windows.Forms.WebBrowser est conçue pour intégrer des pages Web dans votre application. Bien qu'il prenne en charge la navigation personnalisée et les événements de document, sa capacité à capturer du HTML généré dynamiquement est limitée.

L'extrait de code suivant illustre l'utilisation de 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>

Le mshtml.HTMLDocument Interface

L'interface mshtml.HTMLDocument fournit un accès direct à l'objet document HTML sous-jacent. Cependant, il nécessite une navigation et un rendu manuels, ce qui le rend moins pratique pour le contenu généré dynamiquement.

L'extrait de code suivant illustre l'utilisation de 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>

Une approche plus robuste

Pour surmonter les limitations de WebBrowser et mshtml.HTMLDocument, vous pouvez utiliser l'approche suivante :

  1. Créez un contrôle WebBrowser.
  2. Naviguez vers le ciblez l'URL et gérez l'événement DocumentCompleted pour obtenir l'objet mshtml.HTMLDocument2 sous-jacent.
  3. Utilisez une combinaison d'interrogation et de vérification de WebBrowser.IsBusy pour détecter quand le rendu de la page est terminé.
  4. Obtenez la racine élément et interrogez sa propriété OuterHtml jusqu'à ce qu'elle devienne stable.

Exemple de code

Le code C# suivant illustre cette approche :

<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>

Cette approche garantit que vous obtenez le code HTML entièrement rendu même s'il est généré dynamiquement.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn