以编程方式获取页面的屏幕截图

2023-11-26

我正在编写一个供内部使用的专用爬虫和解析器,并且我需要能够截取网页的屏幕截图,以便检查整个过程中使用的颜色。该程序将接收大约十个网址并将它们保存为位图图像。

从那里我计划使用 LockBits 来创建图像中最常用的五种颜色的列表。据我所知,这是获取网页中使用的颜色的最简单方法,但如果有更简单的方法,请提出您的建议。

无论如何,我打算使用ACA WebThumb ActiveX 控件直到我看到价格标签。我对 C# 也相当陌生,只使用了几个月。有没有办法解决我截取网页屏幕截图以提取配色方案的问题?


一种快速但肮脏的方法是使用 WinForms网页浏览器控制并将其绘制到位图。在独立的控制台应用程序中执行此操作有点棘手,因为您必须了解托管控制台应用程序的含义STA线程使用基本的异步编程模式进行控制。但这里有一个可行的概念证明,它将网页捕获为 800x600 BMP 文件:

namespace WebBrowserScreenshotSample
{
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Threading;
    using System.Windows.Forms;

    class Program
    {
        [STAThread]
        static void Main()
        {
            int width = 800;
            int height = 600;

            using (WebBrowser browser = new WebBrowser())
            {
                browser.Width = width;
                browser.Height = height;
                browser.ScrollBarsEnabled = true;

                // This will be called when the page finishes loading
                browser.DocumentCompleted += Program.OnDocumentCompleted;

                browser.Navigate("https://stackoverflow.com/");

                // This prevents the application from exiting until
                // Application.Exit is called
                Application.Run();
            }
        }

        static void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Now that the page is loaded, save it to a bitmap
            WebBrowser browser = (WebBrowser)sender;

            using (Graphics graphics = browser.CreateGraphics())
            using (Bitmap bitmap = new Bitmap(browser.Width, browser.Height, graphics))
            {
                Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                browser.DrawToBitmap(bitmap, bounds);
                bitmap.Save("screenshot.bmp", ImageFormat.Bmp);
            }

            // Instruct the application to exit
            Application.Exit();
        }
    }
}

要编译它,请创建一个新的控制台应用程序并确保添加程序集引用System.Drawing and System.Windows.Forms.

UPDATE:我重写了代码以避免使用 hacky 轮询 WaitOne/DoEvents 模式。此代码应该更接近于以下最佳实践。

更新2:您表明您想要在 Windows 窗体应用程序中使用它。在这种情况下,忘记动态创建WebBrowser控制。你想要的是创建一个隐藏的(Visible = false)实例WebBrowser在您的表单上并按照我上面显示的相同方式使用它。这是另一个示例,显示带有文本框的表单的用户代码部分(webAddressTextBox), 一个按钮 (generateScreenshotButton)和隐藏的浏览器(webBrowser)。当我从事这项工作时,我发现了一个我以前没有处理过的特性——DocumentCompleted 事件实际上可以根据页面的性质多次引发。该示例应该可以正常工作,您可以扩展它以执行您想要的任何操作:

namespace WebBrowserScreenshotFormsSample
{
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Windows.Forms;

    public partial class MainForm : Form
    {
        public MainForm()
        {
            this.InitializeComponent();

            // Register for this event; we'll save the screenshot when it fires
            this.webBrowser.DocumentCompleted += 
                new WebBrowserDocumentCompletedEventHandler(this.OnDocumentCompleted);
        }

        private void OnClickGenerateScreenshot(object sender, EventArgs e)
        {
            // Disable button to prevent multiple concurrent operations
            this.generateScreenshotButton.Enabled = false;

            string webAddressString = this.webAddressTextBox.Text;

            Uri webAddress;
            if (Uri.TryCreate(webAddressString, UriKind.Absolute, out webAddress))
            {
                this.webBrowser.Navigate(webAddress);
            }
            else
            {
                MessageBox.Show(
                    "Please enter a valid URI.",
                    "WebBrowser Screenshot Forms Sample",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);

                // Re-enable button on error before returning
                this.generateScreenshotButton.Enabled = true;
            }
        }

        private void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // This event can be raised multiple times depending on how much of the
            // document has loaded, if there are multiple frames, etc.
            // We only want the final page result, so we do the following check:
            if (this.webBrowser.ReadyState == WebBrowserReadyState.Complete &&
                e.Url == this.webBrowser.Url)
            {
                // Generate the file name here
                string screenshotFileName = Path.GetFullPath(
                    "screenshot_" + DateTime.Now.Ticks + ".png");

                this.SaveScreenshot(screenshotFileName);
                MessageBox.Show(
                    "Screenshot saved to '" + screenshotFileName + "'.",
                    "WebBrowser Screenshot Forms Sample",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);

                // Re-enable button before returning
                this.generateScreenshotButton.Enabled = true;
            }
        }

        private void SaveScreenshot(string fileName)
        {
            int width = this.webBrowser.Width;
            int height = this.webBrowser.Height;
            using (Graphics graphics = this.webBrowser.CreateGraphics())
            using (Bitmap bitmap = new Bitmap(width, height, graphics))
            {
                Rectangle bounds = new Rectangle(0, 0, width, height);
                this.webBrowser.DrawToBitmap(bitmap, bounds);
                bitmap.Save(fileName, ImageFormat.Png);
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以编程方式获取页面的屏幕截图 的相关文章

随机推荐

  • Android - Activity 构造函数与 onCreate

    据我了解 安卓Activities有特定的生命周期onCreate应该被覆盖并用于初始化 但是构造函数中到底发生了什么 是否存在您可以 应该覆盖的情况Activity构造函数也是如此 或者你永远不应该碰它 我假设构造函数永远不应该被使用 因
  • Socket Java 客户端 - Python 服务器

    我正在尝试实现一个 java python 客户端 服务器套接字 客户端是java写的 服务端是python写的 Java客户端 import java io import java net import java lang public
  • AS3:定义命中区域

    我有一个包含位图的影片剪辑 我不想增加命中区域 我知道我可以在它后面添加一个透明形状 但这将通过 ios 的空气进行编译 我不想导致不必要的重绘 有没有办法将矩形定义为点击区域或其他解决方案 有一个特殊的 hitArea 字段用于此目的 c
  • ASP.net 通过内容页访问母版页变量

    我有一个母版页 然后我有一个公共变量 public partial class AdminMaster System Web UI MasterPage protected bool blnShowDialogue false In my
  • Swift 4 上的条形码

    我正在尝试将 mi 应用程序升级到 swift 4 但条形码读取器无法工作 我已经隔离了条形码读取器代码 但仍然无法工作 相机可以工作 但无法检测到条形码 该代码在 swift 3 iOS 10 上运行得很好 这是完整的代码 import
  • 安装 gem 给出“无法构建 gem 本机扩展。”

    I did sudo apt get install ruby ruby dev 我跑 sudo gem install jekyll 但它给出了这个输出 构建本机扩展 这可能需要一段时间 错误 错误 安装 jekyll 错误 无法构建 g
  • 列表中的元素对

    我想转换 1 2 3 4 to 1 2 2 3 3 4 or 1 2 2 3 3 4 在 Clojure 我有 partition 2 1 1 2 3 4 我怎样才能在哈斯克尔做到这一点 我怀疑标准api中有这样的功能 但我找不到它 标准技
  • 字节顺序标记搞砸了 Java 中的文件读取

    我正在尝试使用 Java 读取 CSV 文件 某些文件可能在开头有字节顺序标记 但不是全部 如果存在 字节顺序将与第一行的其余部分一起读取 从而导致字符串比较出现问题 当字节顺序标记存在时 是否有一种简单的方法可以跳过它 EDIT 我已经在
  • PHP中try-catch的性能

    在 php 5 中使用 try catch 语句时需要考虑哪些性能影响 我之前在网上读过一些关于这个主题的旧的 看似相互矛盾的信息 我目前使用的许多框架都是在 php 4 上创建的 缺乏 php 5 的许多优点 因此 我自己在 php 中使
  • Linux/Qt/C++下如何检测USB设备断开

    我正在编写一个系统 X Platform Windows Linux 该系统使用 FTDI USB 芯片与自定义设备进行通信 我使用他们的 D2XX 驱动程序进行设备打开 关闭 读 写 到目前为止 一切都很好 我需要知道设备何时断开连接 以
  • 如何将 C# 代码编译为库而不是可执行文件?

    我在 Visual Studio 2010 中有一个 C 控制台应用程序 它有一个 Main 方法以及一堆实用程序类 我希望这些实用程序类可用于其他解决方案 从网上阅读看来我需要将其编译为类库 DLL 这就是我所做的 进入 Visual S
  • Laravel JSON 响应不带反斜杠

    我正在使用 AJAX 将数据发送到我的控制器 PHP代码 return response gt json request gt root summer uploads store 它返回 http domain test summer up
  • 为什么我无法使用 JQuery .html 添加

    为什么这段代码有效 div error container html div class error No more foo allowed div 但这段代码会导致错误 div error container html div class
  • Log4j2:SMTPAppender 不发送错误或致命级别的邮件

    我发现 log4j2 中的 SMTPAppender 有一些问题 每当记录具有以下级别的事件时error or fatal被创建without举办具有级别的活动info在没有邮件发送并且致命事件消失之前 这是我的 log4j2 配置文件 l
  • 如何将这些 SQL SELECT 查询合并到一个 SELECT 语句中

    如何将这两个 select 语句合并到一个查询中 SELECT SUM incidents AS fires neighborhoods AS fire neighborhoods FROM SELECT FROM fires 2009 i
  • `RefCell` 无法在线程之间安全共享?

    这是一个延续如何在 Rust 的闭包内重用外部作用域的值 为了更好的呈现 开通了新的Q main rs The value will be modified eventually inside main and a http request
  • CSS 响应式左浮动和右浮动(更改哪个 div 位于顶部)?

    我正在这个页面上工作 http www insidemarketblog com test 4 您会看到单词 test 位于左侧浮动的 div 中 图像位于右侧浮动的 div 中 如果调整它的大小 您会看到左浮动的 div 位于顶部 右浮动
  • 打开一个新的弹出窗口并向其发布数据

    我正在使用 jQuery 打开一个弹出窗口 我想在它打开时使用 post 方法向其发送数据 任何人都可以帮助我 提前致谢 我目前正在使用 get 方法传递数据 因此数据是 url 中的一部分 但我不希望数据在 url 中可见 functio
  • 在哪里可以找到 TensorFlow 2.0 的tensorflow.contrib.layers

    我一直在 TensorFlow 中开发机器学习代码contrib layers 我对这个模块很满意 它工作得很好 让我能够充分控制我的模型 然而 TensorFlow 2 0将完全删除contrib模块和新的keras模块在没有额外努力的情
  • 以编程方式获取页面的屏幕截图

    我正在编写一个供内部使用的专用爬虫和解析器 并且我需要能够截取网页的屏幕截图 以便检查整个过程中使用的颜色 该程序将接收大约十个网址并将它们保存为位图图像 从那里我计划使用 LockBits 来创建图像中最常用的五种颜色的列表 据我所知 这