Saltar al contenido

Uso de CefSharp.Offscreen para recuperar una página web que requiere Javascript para renderizar

Mantén la atención porque en esta división hallarás el resultado que buscas.

Solución:

Sé que estoy haciendo algo de arqueología reviviendo una publicación de 2 años, pero una respuesta detallada puede ser útil para otra persona.

Así que sí, Cefsharp.Offscreen es apto para la tarea.

Aquí debajo hay una clase que manejará toda la actividad del navegador.

using System;
using System.IO;
using System.Threading;
using CefSharp;
using CefSharp.OffScreen;

namespace [whatever]

    public class Browser
    

        /// 
        /// The browser page
        /// 
        public ChromiumWebBrowser Page  get; private set; 
        /// 
        /// The request context
        /// 
        public RequestContext RequestContext  get; private set; 

        // chromium does not manage timeouts, so we'll implement one
        private ManualResetEvent manualResetEvent = new ManualResetEvent(false);

        public Browser()
        
            var settings = new CefSettings()
            
                //By default CefSharp will use an in-memory cache, you need to     specify a Cache Folder to persist data
                CachePath =     Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\Cache"),
            ;

            //Autoshutdown when closing
            CefSharpSettings.ShutdownOnExit = true;

            //Perform dependency check to make sure all relevant resources are in our     output directory.
            Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

            RequestContext = new RequestContext();
            Page = new ChromiumWebBrowser("", null, RequestContext);
            PageInitialize();
        

        /// 
        /// Open the given url
        /// 
        /// the url
        /// 
        public void OpenUrl(string url)
        
            try
            
                Page.LoadingStateChanged += PageLoadingStateChanged;
                if (Page.IsBrowserInitialized)
                
                    Page.Load(url);

                    //create a 60 sec timeout 
                    bool isSignalled = manualResetEvent.WaitOne(TimeSpan.FromSeconds(60));
                    manualResetEvent.Reset();

                    //As the request may actually get an answer, we'll force stop when the timeout is passed
                    if (!isSignalled)
                    
                        Page.Stop();
                    
                
            
            catch (ObjectDisposedException)
            
                //happens on the manualResetEvent.Reset(); when a cancelation token has disposed the context
            
            Page.LoadingStateChanged -= PageLoadingStateChanged;
        

        /// 
        /// Manage the IsLoading parameter
        /// 
        /// 
        /// 
        private void PageLoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
        
            // Check to see if loading is complete - this event is called twice, one when loading starts
            // second time when it's finished
            if (!e.IsLoading)
            
                manualResetEvent.Set();
            
        

        /// 
        /// Wait until page initialization
        /// 
        private void PageInitialize()
        
            SpinWait.SpinUntil(() => Page.IsBrowserInitialized);
        
    

Ahora en mi aplicación solo necesito hacer lo siguiente:

public MainWindow()

    InitializeComponent();
    _browser = new Browser();


private async void GetGoogleSource()

    _browser.OpenUrl("http://icanhazip.com/");
    string source = await _browser.Page.GetSourceAsync();

Y aquí está el string yo obtengo

"

NotGonnaGiveYouMyIP:)n

"

Si no puede obtener una versión sin interfaz de Chromium para ayudarlo, puede probar node.js y jsdom. Fácil de instalar y jugar una vez que tenga el nodo en funcionamiento. Puede ver ejemplos simples en Github README donde abren una URL, ejecutan todo javascript, incluido cualquier código de javascript personalizado (ejemplo: bits de jQuery para contar algún tipo de elementos), y luego tiene el HTML en la memoria para hacer lo que quiere . Puedes simplemente hacer $(‘body’).html() y obtener un string, como en su pseudocódigo. (Esto incluso funciona para cosas como generar gráficos SVG, ya que son solo más nodos de árbol XML).

Si necesita esto como parte de una aplicación C# más grande que necesita distribuir, su idea de usar CefSharp.Offscreen parece razonable. Un enfoque podría ser hacer que las cosas funcionen con CefSharp.WinForms o CefSharp.WPF primero, donde literalmente puede ver las cosas, luego intente con CefSharp.Offscreen más tarde cuando todo funcione. Incluso puede hacer que JavaScript se ejecute en el navegador en pantalla para desplegar body.innerHTML y devolverlo como un string al lado C# de las cosas antes de quedarse sin cabeza. Si eso funciona, el resto debería ser fácil.

Tal vez comience con CefSharp.MinimalExample y obtenga esa compilación, luego ajústela según sus necesidades. Debe poder configurar webBrowser.Address en su código C#, y necesita saber cuándo se cargó la página, luego debe llamar a webBrowser.EvaluateScriptAsync(“.. código JS ..”) con su código JavaScript (como un string) que hará algo como se describe (devolviendo bodyElement.innerHTML como un string).

Te invitamos a añadir valor a nuestro contenido informacional dando tu experiencia en las notas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *