• PuppeteerSharp 在asp.net中使用 PuppeteerSharp生命周期管理


    2020-12-22 更新,以下代码有坑不要使用,回过头来看,发现以前写的东西好烂呀,哈哈哈哈。。。

    博客就放这里给自己留个纪念。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

    1.PuppeteerSharp在asp.net中使用的坑:

      1.如果使用nuget下载PuppeteerSharp 则还需要添加PuppeteerSharp.AspNetFramework包依赖。

      2.需要下载chromium 浏览器文件 参考https://www.cnblogs.com/cdyy/p/PuppeteerSharp.html 这篇博客。

      3.手动添加依赖包,参考如下:

          a.通过nuget 添加以下包

      左图是包版本,右图是需要下载的包。

    2.将PuppeteerSharp 生命周期交给autofac管理

      前提:一个asp.net 应用程序只需要启动一个chromium 进程,当寄宿在IIS中的asp.net应用程序 停止或被回收 时,chromium 进程也需要被关闭掉。

         通过启动的chromium浏览器开启“Page”页,每一次的请求打开的page页(一个或多个),将在请求结束后自动销毁掉。

      这里提供下思路,参考代码如下: 

      1).创建 IChromiumBrowser,这里封装了下PuppeteerSharp 的 Browser 对象。

        public interface IChromiumBrowser : IDisposable,IAsyncDisposable
        {  
            Task<Browser> GetBrowserAsync();
        }
    

           实现

    public class ChromiumBrowserAspNet : IChromiumBrowser
        {
            private readonly LaunchOptions _launchOptions;
    
            public ChromiumBrowserAspNet()
            {
                _launchOptions = new LaunchOptions();
                DetectBrowserFile();
            }
    
            private Browser _browser;
            private bool _existsBrowserFile;
            private static readonly object Lock = new object();
    
            public async Task<Browser> GetBrowserAsync()
            {
                if (_browser != null) return _browser;
    
                await Task.Run(() =>
                {
                    lock (Lock)
                    {
                        if (_browser == null)
                        {
                            //请提前下载好浏览器相关文件
                            //await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
                            _browser = Puppeteer.LaunchAsync(_launchOptions).Result;
                            //如果浏览器进程被其他操作强制关闭,释放_browser。
                            _browser.Disconnected += (a, b) =>
                            {
                                if (_browser == null) return;
                                Dispose(true);
                            };
                        }
                    }
                });
                return _browser;
            }
    
            private void DetectBrowserFile()
            {
                if (_existsBrowserFile) return;
                string platForm = null;
                if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    platForm = Platform.MacOS.ToString();
                }
    
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    platForm = Platform.Linux.ToString();
                }
    
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    platForm = RuntimeInformation.OSArchitecture == Architecture.X64 ? Platform.Win64.ToString() : Platform.Win32.ToString();
                }
    
                string folder = Path.Combine(Directory.GetCurrentDirectory(), ".local-chromium");
                string filePath = Path.Combine(folder, $"{platForm}-{BrowserFetcher.DefaultRevision}");
                _existsBrowserFile = new DirectoryInfo(filePath).Exists;
                if (!_existsBrowserFile)
                {
                    throw new Exception($"{filePath}");
                }
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if (disposing)
                {
                    _browser?.Dispose();
                }
                _browser = null;
            }
    
            public void Dispose()
            {
                Dispose(disposing: true);
                GC.SuppressFinalize(this);
            }
    
            public async ValueTask DisposeAsync()
            {
                await DisposeAsyncCore();
    
                Dispose(disposing: false);
                GC.SuppressFinalize(this);
            }
    
            protected virtual async ValueTask DisposeAsyncCore()
            {
                if (_browser != null)
                {
                    await _browser.DisposeAsync();
                }
    
                _browser = null;
            }
    
        }
    

       2).通过browser创建page 页 。名字你自己取,我的叫IPuppeteerSharpContext

        public interface IPuppeteerSharpContext : IDisposable, IAsyncDisposable
        {
    
            List<IPuppeteerSharpPage> PuppeteerSharpPages { get; }
            Task<List<IPuppeteerSharpPage>> GetPagesAsync(List<PageSetting> pageSettings);
          Task<IPuppeteerSharpPage> GetPageAsync(PageSetting pageSetting);
        }
    

        实现

        public class PuppeteerSharpContextAspNet : IPuppeteerSharpContext
        {
            private readonly IChromiumBrowser _chromiumBrowser;
    
            public PuppeteerSharpContextAspNet(IChromiumBrowser chromiumBrowser)
            {
                _chromiumBrowser = chromiumBrowser;
                _puppeteerSharpPages = new List<IPuppeteerSharpPage>();
            }
    
            private Browser _browser;
    
            private async Task StarUpPageAsync()
            {
                if (_browser == null)
                {
                    _browser = await _chromiumBrowser.GetBrowserAsync();
                }
            }
    
            private List<IPuppeteerSharpPage> _puppeteerSharpPages;
    
            public List<IPuppeteerSharpPage> PuppeteerSharpPages => _puppeteerSharpPages;
    
            public async Task<List<IPuppeteerSharpPage>> GetPagesAsync(List<PageSetting> pageSettings)
            {
                if (pageSettings == null) throw new Exception("pageSettings is null");
    
                await StarUpPageAsync();
    
                var list = new List<IPuppeteerSharpPage>();
                pageSettings.ForEach(item =>
                {
                    var page = new PuppeteerSharpPage(item, _browser);
                    list.Add(page);
                    _puppeteerSharpPages.Add(page);
                });
                return list;
            }
    
    
            public async Task<IPuppeteerSharpPage> GetPageAsync(PageSetting pageSetting)
            {
                if (pageSetting == null) throw new Exception("pageSetting is null");
    
                await StarUpPageAsync();
    
                var page = new PuppeteerSharpPage(pageSetting, _browser);
                _puppeteerSharpPages.Add(page);
                return page;
            }
    
    
            protected virtual void Dispose(bool disposing)
            {
                if (disposing)
                {
                    _puppeteerSharpPages?.ForEach(item => item.Dispose());
                }
                _puppeteerSharpPages = null;
            }
    
            public void Dispose()
            {
                Dispose(disposing: true);
                GC.SuppressFinalize(this);
            }
    
            public async ValueTask DisposeAsync()
            {
                await DisposeAsyncCore();
                Dispose(disposing: false);
                GC.SuppressFinalize(this);
            }
    
            protected virtual async ValueTask DisposeAsyncCore()
            {
                if (_puppeteerSharpPages != null)
                {
                    foreach (var item in _puppeteerSharpPages)
                    {
                        await item.DisposeAsync();
                    }
                }
                _puppeteerSharpPages = null;
            }
        }
    

        IPuppeteerSharpPage和PuppeteerSharpPage 根据你自己情况去实现。

      3).将ChromiumBrowser 、“Page”交给autofac管理,参考 https://www.cnblogs.com/bluesummer/p/9041802.html  “IRegisteredObject”

        /// <summary>
        /// Asp.Net IIS宿主环境配置 <see cref="WebAppEnviroment" />.
        /// </summary>
        public class WebAppEnviroment : IRegisteredObject
        {
            public WebAppEnviroment()
            {
                HostingEnvironment.RegisterObject(this);
            }
    
            private static IChromiumBrowser _chromiumBrowser;
    
            public void RegisterBrowserModule(ContainerBuilder builder)
            {
                builder.Register(context =>
                {
                    IChromiumBrowser browser = new ChromiumBrowserAspNet();
                    _chromiumBrowser = browser;
                    return browser;
                }).As<IChromiumBrowser>().SingleInstance();
                builder.RegisterType<PuppeteerSharpContextAspNet>().As<IPuppeteerSharpContext>().InstancePerRequest();
            }
    
            public void Stop(bool immediate)
            {
                if (_chromiumBrowser != null)
                {
                    _chromiumBrowser.Dispose();
                    _chromiumBrowser = null;
                }
                HostingEnvironment.UnregisterObject(this);
            }
        }
    
        public static class ContainerBuilderExtsionTes
        {
            public static void RegisterBrowserModule(this ContainerBuilder builder)
            {
                var app = new WebAppEnviroment();
                app.RegisterBrowserModule(builder);
            }
        }
    

      这里是将ChromiumBrowser创建成了单例,因为只需要存在一个(只需要存在一个browser 浏览器),IPuppeteerSharpContext 则是每次请求一个只创建一个实例,然后通过 IPuppeteerSharpContext去创建page页和释放page页。

      大致思路就是这样,也不知道有没有讲清楚。 这里不提供具体实现代码。

  • 相关阅读:
    部署至Oracle数据库的注意事项
    当在centos上面部署项目时,mysql的一些驱动安装不上,
    drf利用redis做缓存是发生一点错误提示
    python字符串前面加个u代表什么
    在学习数据分析时,安装anaconda时遇到一点问题
    在使用scrapy框架爬取sina时,常见保存
    在linux上scrapyd部署scrapy项目时出现service_identity,并且不能识别其中的一个opentype模块
    如何在mysql增加一个和root权限一样的用户,安排
    mysq的root密码忘记,原来还有更优雅的解法
    mysql远程连接阿里云的Ubuntu服务器
  • 原文地址:https://www.cnblogs.com/youlicc/p/14021953.html
Copyright © 2020-2023  润新知