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