2016-03-09 53 views
7

Sto utilizzando aCefSharp.Wpf.ChromiumWebBrowser (versione 47.0.3.0) per caricare una pagina Web. Qualche punto dopo che la pagina è stata caricata, voglio ottenere il codice sorgente.Ottieni codice sorgente HTML dal browser CefSharp

mi hanno chiamato:

wb.GetBrowser().MainFrame.GetSourceAsync() 

però non risulta essere di ritorno tutto il codice sorgente (credo che questo è perché ci sono frame figlio).

se chiamo:

wb.GetBrowser().MainFrame.ViewSource() 

posso vedere elenca tutto il codice sorgente (inclusi i telai interni).

Mi piacerebbe ottenere lo stesso risultato di ViewSource(). Qualcuno potrebbe indicarmi la direzione giusta per favore?

Update - Codice Aggiunto esempio

Nota: L'indirizzo del browser web sta puntando troppo funzionerà solo fino al 2016/10/03. Dopodiché potrebbe visualizzare dati diversi che non sono quello che guarderei.

Nel frmSelection.xaml il file

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

Negli frmSelection.xaml.cs il file

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

} 
+0

Puoi condividere altro codice? Non riesco a riprodurre il tuo problema, ottengo lo stesso testo con 'GetSourceAsync' come con' ViewSource'. Provato con 'Address' impostato su' http: // stackoverflow.com' (ha due frame, uno 'iframe' e il frame principale) –

+0

Grazie per dare un'occhiata. Ho aggiunto la fonte di esempio al post originale. – Scott

risposta

11

non credo che mi riesce quasi mai questa soluzione DispatcherTimer. Io farei così:

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

ho fatto un diff sull'uscita del ViewSource e il testo nella variabile html e sono gli stessi, quindi non posso riprodurre il problema qui.

Detto questo, ho notato che il frame principale viene caricato abbastanza tardi, quindi è necessario attendere un po 'fino a quando il blocco note si apre con la fonte.

+0

Grazie per il feedback sul mio codice, l'ho aggiornato per riflettere il tuo esempio. Ho eseguito il codice su un altro computer da quando ho postato l'esempio e ottengo gli stessi risultati (entrambi restituiscono il codice sorgente completo). Posso solo concludere che c'è qualcosa di strano in corso con la mia macchina e prenderò in considerazione l'idea di fare un formato. – Scott

1

Stavo avendo lo stesso problema cercando di ottenere clic su e elemento situato in un frame e non sul frame principale. Utilizzando l'esempio nella sua risposta, ho scritto il seguente metodo di estensione:

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

Se si dispone di un "tramite" sul modulo per il modulo che contiene questo metodo è possibile fare qualcosa di simile:

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

Ovviamente è necessario assicurarsi che il caricamento della pagina sia completo prima di usarlo, ma ho intenzione di usarlo molto. Spero che sia d'aiuto!

Jim