• C#实现网页加载后将页面截取成长图片


    背景

    最近再做一个需求,需要对网页生成预览图,如下图

    但是网页千千万,总不能一个个打开,截图吧;于是想着能不能使用代码来实现网页的截图。其实要实现这个功能,无非就是要么实现一个仿真浏览器,要么调用系统浏览器,再进行截图操作。

    代码实现

    1、启用线程Thread

     void startPrintScreen(ScreenShotParam requestParam)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));
                thread.SetApartmentState(ApartmentState.STA);
                thread.Start(requestParam);
                if (requestParam.Wait)
                {
                    thread.Join();
                    FileInfo result = new FileInfo(requestParam.SavePath);
                    long minSize = 1 * 1024;// 太小可能是空白圖,重抓
                    int maxRepeat = 2;                
                    while ((!result.Exists || result.Length <= minSize) && maxRepeat > 0)
                    {
                        thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));
                        thread.SetApartmentState(ApartmentState.STA);
                        thread.Start(requestParam);
                        thread.Join();
                        maxRepeat--;
                    }
                }
            }

    2、模拟浏览器WebBrowser

    void do_PrintScreen(object param)
            {
                try
                {
                    ScreenShotParam screenShotParam = (ScreenShotParam)param;
                    string requestUrl = screenShotParam.Url;
                    string savePath = screenShotParam.SavePath;
                    WebBrowser wb = new WebBrowser();
                    wb.ScrollBarsEnabled = false;
                    wb.ScriptErrorsSuppressed = true;
                    wb.Navigate(requestUrl);
                    logger.Debug("wb.Navigate");
                    DateTime startTime = DateTime.Now;
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 10, 0);// 10 second
                    while (wb.ReadyState != WebBrowserReadyState.Complete)
                    {
                        Application.DoEvents();
                        if (DateTime.Now - startTime > waitTime)
                        {
                            wb.Dispose();
                            logger.Debug("wb.Dispose() timeout");
                            return;
                        }
                    }
    
                    wb.Width = screenShotParam.Left + screenShotParam.Width + screenShotParam.Left; // wb.Document.Body.ScrollRectangle.Width (避掉左右側的邊線);
                    wb.Height = screenShotParam.Top + screenShotParam.Height; // wb.Document.Body.ScrollRectangle.Height;
                    wb.ScrollBarsEnabled = false;
                    wb.Document.Body.Style = "overflow:hidden";//hide scroll bar
                    var doc = (wb.Document.DomDocument) as mshtml.IHTMLDocument2;
                    var style = doc.createStyleSheet("", 0);
                    style.cssText = @"img { border-style: none; }";
    
                    Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
                    wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));
                    wb.Dispose();
                    logger.Debug("wb.Dispose()");
    
                    bitmap = CutImage(bitmap, new Rectangle(screenShotParam.Left, screenShotParam.Top, screenShotParam.Width, screenShotParam.Height));
                    bool needResize = screenShotParam.Width > screenShotParam.ResizeMaxWidth || screenShotParam.Height > screenShotParam.ResizeMaxWidth;
                    if (needResize)
                    {
                        double greaterLength = bitmap.Width > bitmap.Height ? bitmap.Width : bitmap.Height;
                        double ratio = screenShotParam.ResizeMaxWidth / greaterLength;
                        bitmap = Resize(bitmap, ratio);
                    }
    
                    bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Gif);
                    bitmap.Dispose();
                    logger.Debug("bitmap.Dispose();");
                    logger.Debug("finish");
    
                }
                catch (Exception ex)
                {
                    logger.Info($"exception: {ex.Message}");
                }
            }

    3、截图操作

    private static Bitmap CutImage(Bitmap source, Rectangle section)
            {
                // An empty bitmap which will hold the cropped image
                Bitmap bmp = new Bitmap(section.Width, section.Height);
                //using (Bitmap bmp = new Bitmap(section.Width, section.Height))
                {
                    Graphics g = Graphics.FromImage(bmp);
    
                    // Draw the given area (section) of the source image
                    // at location 0,0 on the empty bitmap (bmp)
                    g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
    
                    return bmp;
                }
            }
    
            private static Bitmap Resize(Bitmap originImage, Double times)
            {
                int width = Convert.ToInt32(originImage.Width * times);
                int height = Convert.ToInt32(originImage.Height * times);
    
                return ResizeProcess(originImage, originImage.Width, originImage.Height, width, height);
            }

    完整代码

     public static string ScreenShotAndSaveAmazonS3(string account, string locale, Guid rule_ID, Guid template_ID)
            {
              
                //新的Template
                var url = string.Format("https://xxxx/public/previewtemplate?showTemplateName=0&locale={0}&inputTemplateId={1}&inputThemeId=&Account={2}",
                    locale,
                    template_ID,
                    account
                    );
                
    
                var tempPath = Tools.GetAppSetting("TempPath");
    
                //路徑準備
                var userPath = AmazonS3.GetS3UploadDirectory(account, locale, AmazonS3.S3SubFolder.Template);
                var fileName = string.Format("{0}.gif", template_ID);
                var fullFilePath = Path.Combine(userPath.LocalDirectoryPath, fileName);
                logger.Debug("userPath: {0}, fileName: {1}, fullFilePath: {2}, url:{3}", userPath, fileName, fullFilePath, url);
     
                //開始截圖,並暫存在本機
                var screen = new Screen();
                screen.ScreenShot(url, fullFilePath);
    
                //將截圖,儲存到 Amazon S3
                //var previewImageUrl = AmazonS3.UploadFile(fullFilePath, userPath.RemotePath + fileName);
    
                return string.Empty;
            }
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace PrintScreen.Common
    {
        public class Screen
        {
            protected static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    
            public void ScreenShot(string url, string path
                , int width = 400, int height = 300
                , int left = 50, int top = 50
                , int resizeMaxWidth = 200, int wait = 1)
            {
                if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(path))
                {
                    ScreenShotParam requestParam = new ScreenShotParam
                    {
                        Url = url,
                        SavePath = path,
                        Width = width,
                        Height = height,
                        Left = left,
                        Top = top,
                        ResizeMaxWidth = resizeMaxWidth,
                        Wait = wait != 0
                    };
                    startPrintScreen(requestParam);
                }
            }
    
            void startPrintScreen(ScreenShotParam requestParam)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));
                thread.SetApartmentState(ApartmentState.STA);
                thread.Start(requestParam);
                if (requestParam.Wait)
                {
                    thread.Join();
                    FileInfo result = new FileInfo(requestParam.SavePath);
                    long minSize = 1 * 1024;// 太小可能是空白圖,重抓
                    int maxRepeat = 2;                
                    while ((!result.Exists || result.Length <= minSize) && maxRepeat > 0)
                    {
                        thread = new Thread(new ParameterizedThreadStart(do_PrintScreen));
                        thread.SetApartmentState(ApartmentState.STA);
                        thread.Start(requestParam);
                        thread.Join();
                        maxRepeat--;
                    }
                }
            }
    
            void do_PrintScreen(object param)
            {
                try
                {
                    ScreenShotParam screenShotParam = (ScreenShotParam)param;
                    string requestUrl = screenShotParam.Url;
                    string savePath = screenShotParam.SavePath;
                    WebBrowser wb = new WebBrowser();
                    wb.ScrollBarsEnabled = false;
                    wb.ScriptErrorsSuppressed = true;
                    wb.Navigate(requestUrl);
                    logger.Debug("wb.Navigate");
                    DateTime startTime = DateTime.Now;
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 10, 0);// 10 second
                    while (wb.ReadyState != WebBrowserReadyState.Complete)
                    {
                        Application.DoEvents();
                        if (DateTime.Now - startTime > waitTime)
                        {
                            wb.Dispose();
                            logger.Debug("wb.Dispose() timeout");
                            return;
                        }
                    }
    
                    wb.Width = screenShotParam.Left + screenShotParam.Width + screenShotParam.Left; // wb.Document.Body.ScrollRectangle.Width (避掉左右側的邊線);
                    wb.Height = screenShotParam.Top + screenShotParam.Height; // wb.Document.Body.ScrollRectangle.Height;
                    wb.ScrollBarsEnabled = false;
                    wb.Document.Body.Style = "overflow:hidden";//hide scroll bar
                    var doc = (wb.Document.DomDocument) as mshtml.IHTMLDocument2;
                    var style = doc.createStyleSheet("", 0);
                    style.cssText = @"img { border-style: none; }";
    
                    Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
                    wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));
                    wb.Dispose();
                    logger.Debug("wb.Dispose()");
    
                    bitmap = CutImage(bitmap, new Rectangle(screenShotParam.Left, screenShotParam.Top, screenShotParam.Width, screenShotParam.Height));
                    bool needResize = screenShotParam.Width > screenShotParam.ResizeMaxWidth || screenShotParam.Height > screenShotParam.ResizeMaxWidth;
                    if (needResize)
                    {
                        double greaterLength = bitmap.Width > bitmap.Height ? bitmap.Width : bitmap.Height;
                        double ratio = screenShotParam.ResizeMaxWidth / greaterLength;
                        bitmap = Resize(bitmap, ratio);
                    }
    
                    bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Gif);
                    bitmap.Dispose();
                    logger.Debug("bitmap.Dispose();");
                    logger.Debug("finish");
    
                }
                catch (Exception ex)
                {
                    logger.Info($"exception: {ex.Message}");
                }
            }
    
            private static Bitmap CutImage(Bitmap source, Rectangle section)
            {
                // An empty bitmap which will hold the cropped image
                Bitmap bmp = new Bitmap(section.Width, section.Height);
                //using (Bitmap bmp = new Bitmap(section.Width, section.Height))
                {
                    Graphics g = Graphics.FromImage(bmp);
    
                    // Draw the given area (section) of the source image
                    // at location 0,0 on the empty bitmap (bmp)
                    g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
    
                    return bmp;
                }
            }
    
            private static Bitmap Resize(Bitmap originImage, Double times)
            {
                int width = Convert.ToInt32(originImage.Width * times);
                int height = Convert.ToInt32(originImage.Height * times);
    
                return ResizeProcess(originImage, originImage.Width, originImage.Height, width, height);
            }
    
            private static Bitmap ResizeProcess(Bitmap originImage, int oriwidth, int oriheight, int width, int height)
            {
                Bitmap resizedbitmap = new Bitmap(width, height);
                //using (Bitmap resizedbitmap = new Bitmap(width, height))
                {
                    Graphics g = Graphics.FromImage(resizedbitmap);
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    g.Clear(Color.Transparent);
                    g.DrawImage(originImage, new Rectangle(0, 0, width, height), new Rectangle(0, 0, oriwidth, oriheight), GraphicsUnit.Pixel);
                    return resizedbitmap;
                }
            }
    
        }
    
        class ScreenShotParam
        {
            public string Url { get; set; }
            public string SavePath { get; set; }
            public int Width { get; set; }
            public int Height { get; set; }
            public int Left { get; set; }
            public int Top { get; set; }
            /// <summary>
            /// 長邊縮到指定長度
            /// </summary>
            public int ResizeMaxWidth { get; set; }
            public bool Wait { get; set; }
        }
    
    }

    效果

     完成,达到预期的效果。

  • 相关阅读:
    Leetcode:50. Pow(x, n)
    loj 2759「JOI 2014 Final」飞天鼠
    bzoj 3569 DZY Loves Chinese II
    CF407D Largest Submatrix 3
    bzoj 3837 pa2013 Filary
    bzoj 4722 由乃
    CF1105E Helping Hiasat
    loj 6043「雅礼集训 2017 Day7」蛐蛐国的修墙方案
    luogu P2605 [ZJOI2010]基站选址
    luogu P3226 [HNOI2012]集合选数
  • 原文地址:https://www.cnblogs.com/lyl6796910/p/14250948.html
Copyright © 2020-2023  润新知