web-dev-qa-db-fra.com

Obtenez le code source HTML à partir du navigateur Web CefSharp

J'utilise aCefSharp.Wpf.ChromiumWebBrowser (Version 47.0.3.0) pour charger une page Web. Un moment après le chargement de la page, je veux obtenir le code source.

J'ai appelé:

wb.GetBrowser().MainFrame.GetSourceAsync()

cependant, il ne semble pas renvoyer tout le code source (je pense que c'est parce qu'il y a des cadres enfants).

Si j'appelle:

wb.GetBrowser().MainFrame.ViewSource() 

Je peux voir qu'il répertorie tout le code source (y compris les cadres internes).

Je voudrais obtenir le même résultat que ViewSource (). Quelqu'un pourrait-il m'orienter dans la bonne direction, s'il vous plaît?

Mise à jour - Exemple de code ajouté

Remarque: l'adresse que le navigateur Web pointe également ne fonctionnera que jusqu'au 10/03/2016 inclus. Après cela, il peut afficher différentes données qui ne sont pas ce que je regarderais.

Dans le fichier frmSelection.xaml

<cefSharp:ChromiumWebBrowser Name="wb" Grid.Column="1" Grid.Row="0" />

Dans le fichier frmSelection.xaml.cs

public partial class frmSelection : UserControl
{
    private System.Windows.Threading.DispatcherTimer wbTimer = new System.Windows.Threading.DispatcherTimer();

    public frmSelection()
    {

         InitializeComponent();

         // This timer will start when a web page has been loaded.
         // It will wait 4 seconds and then call wbTimer_Tick which 
         // will then see if data can be extracted from the web page.
         wbTimer.Interval = new TimeSpan(0, 0, 4);
         wbTimer.Tick += new EventHandler(wbTimer_Tick);

         wb.Address = "http://www.racingpost.com/horses2/cards/card.sd?race_id=644222&r_date=2016-03-10#raceTabs=sc_";

         wb.FrameLoadEnd += new EventHandler<CefSharp.FrameLoadEndEventArgs>(wb_FrameLoadEnd);

    }

        void wb_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
        {
            if (wbTimer.IsEnabled)
                wbTimer.Stop();

            wbTimer.Start();
        }

    void wbTimer_Tick(object sender, EventArgs e)
    {
        wbTimer.Stop();
        string html = GetHTMLFromWebBrowser();
    }

    private string GetHTMLFromWebBrowser()
    {
         // call the ViewSource method which will open up notepad and display the html.
         // this is just so I can compare it to the html returned in GetSourceAsync()
         // This is displaying all the html code (including child frames)
            wb.GetBrowser().MainFrame.ViewSource();

         // Get the html source code from the main Frame.
            // This is displaying only code in the main frame and not any child frames of it.
            Task<String> taskHtml = wb.GetBrowser().MainFrame.GetSourceAsync();

            string response = taskHtml.Result;
     return response;
  }

}
12
Scott

Je ne pense pas avoir tout à fait cette solution DispatcherTimer. Je le ferais comme ça:

public frmSelection()
{
    InitializeComponent();

    wb.FrameLoadEnd += WebBrowserFrameLoadEnded;
    wb.Address = "http://www.racingpost.com/horses2/cards/card.sd?race_id=644222&r_date=2016-03-10#raceTabs=sc_";
}

private void WebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
    if (e.Frame.IsMain)
    {
        wb.ViewSource();
        wb.GetSourceAsync().ContinueWith(taskHtml =>
        {
            var html = taskHtml.Result;
        });
    }
}

J'ai fait un diff sur la sortie de ViewSource et le texte dans la variable html et ils sont les mêmes, donc je ne peux pas reproduire votre problème ici.

Cela dit, j'ai remarqué que le cadre principal est chargé assez tard, vous devez donc attendre un certain temps jusqu'à ce que le bloc-notes apparaisse avec la source.

17
Szabolcs Dézsi

J'avais le même problème en essayant d'obtenir un clic sur un élément situé dans un cadre et non sur le cadre principal. En utilisant l'exemple dans votre réponse, j'ai écrit la méthode d'extension suivante:

        public static IFrame GetFrame(this ChromiumWebBrowser browser, string FrameName)
    {
        IFrame frame = null;

        var identifiers = browser.GetBrowser().GetFrameIdentifiers();

        foreach (var i in identifiers)
        {
            frame = browser.GetBrowser().GetFrame(i);
            if (frame.Name == FrameName)
                return frame;
        }

        return null;
    }

Si vous avez une "utilisation" sur votre formulaire pour le module qui contient cette méthode, vous pouvez faire quelque chose comme:

var frame = browser.GetFrame("nameofframe");
        if (frame != null)
        {
            string HTML = await frame.GetSourceAsync();
        }

Bien sûr, vous devez vous assurer que le chargement de la page est terminé avant de l'utiliser, mais je prévois de l'utiliser beaucoup. J'espère que cela aide!

Jim

1
Jim Wilcox