Using CefSharp.Offscreen to retrieve a web page that requires Javascript to render

前端 未结 2 983
情话喂你
情话喂你 2020-12-29 00:16

I have what is hopefully a simple task, but it\'s going to take someone that\'s versed in CefSharp to solve it.

I have an url that I want to retrieve the HTML from.

2条回答
  •  滥情空心
    2020-12-29 00:32

    I know I am doing some archaeology reviving a 2yo post, but a detailed answered may be of use for someone else.

    So yes, Cefsharp.Offscreen is fit to the task.

    Here under is a class which will handle all the browser activity.

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

    Now in my app I just need to do the following:

    public MainWindow()
    {
        InitializeComponent();
        _browser = new Browser();
    }
    
    private async void GetGoogleSource()
    {
        _browser.OpenUrl("http://icanhazip.com/");
        string source = await _browser.Page.GetSourceAsync();
    }
    

    And here is the string I get

    "

    NotGonnaGiveYouMyIP:)\n
    "

提交回复
热议问题