【问题标题】:Saving a web page as image将网页另存为图像
【发布时间】:2011-05-07 01:10:31
【问题描述】:

作为一个爱好项目,我正在探索将网页 (HTML) 保存为图像的方法,主要以编程方式使用 c/c++/javascript/java。到目前为止,我遇到了以下几种方式:

  1. 获取页面正文的IHTMLElement,并用它来查询IHTMLElementRender,然后使用它的DrawToDC方法(Ref: http://www.codeproject.com/KB/IP/htmlimagecapture.aspx)。但问题是它不适用于所有页面(主要是嵌入 iframe 的页面)。

  2. 我能想到的另一种方法是使用一些 Web 浏览器组件,当页面完全加载时,然后使用 BitBltRef: http://msdn.microsoft.com/en-us/library/dd183370%28VS.85%29.aspx)捕获它。但问题是我请求的页面可能比我的屏幕尺寸长,它不适合网络浏览器组件。

非常感谢任何解决上述问题的方向/建议或替代方法。

【问题讨论】:

    标签: java javascript c++ html image


    【解决方案1】:

    如果您使用 Python,则有 pywebshotwebkit2png。不过,它们都有一些依赖关系。

    编辑:糟糕,Python 不在您的首选语言列表中。无论如何我都会把这个答案留在这里,因为你说的是​​“大部分”而不是“唯一”。

    【讨论】:

    • 感谢 kijin .. 我考虑过但为了使用它我必须学习 python :)
    【解决方案2】:

    另一个(有点迂回)选项是运行像 Tomcat 这样的服务器并使用 Java 调用命令行工具来截取屏幕截图。谷歌搜索“命令行屏幕截图窗口”会出现一些看起来合理的可能性。但是,除了运行服务器之外,我不知道从 javascript 运行本地可执行文件的好方法。不过,这种方法可以使它跨浏览器,这是一个加分项(只需在需要屏幕截图时对脚本进行 ajax 调用)。

    不幸的是,我实际上并不知道如何部署战争文件。使用Tomcat可能会更麻烦;我提到它是因为 Java 是一种首选语言。运行 XAMPP 并使用这个 PHP sn-p 会相当简单,而且你真的不需要学习 php:

    <?php
    exec("/path/to/exec args");
    ?>
    

    编辑

    您知道,我不确定这是否真的回答了您的问题。这是一种方式,但它来自 JavaScript 端而不是脚本端。如果你想通过脚本来实现,你总是可以使用 Selenium。支持截取整个页面的截图,并且可以通过Java控制。

    【讨论】:

    • 谢谢,能不能在这里详细说明一下tomcat和java的使用。假设我想访问stackoverflow.com 那么tomcat 将适合哪里。 Selenium 是一个不错的选择,将对其进行研究。
    • 其实我不知道在Tomcat上部署一个web应用程序有多复杂。使用 XAMPP 和 PHP sn-p 可能更容易。编辑了我的答案。
    【解决方案3】:

    终于可以通过这两篇文章破解了:

    1. http://www.codeproject.com/KB/GDI-plus/WebPageSnapshot.aspx[c#代码-IE]
    2. http://www.codeproject.com/KB/graphics/IECapture.aspx [c++ & GDI - IE]

    无法分享代码,但以上两篇文章将为您提供最佳解决方案。

    也可以看看:

    https://addons.mozilla.org/en-US/firefox/addon/3408/ [firefox + javascript]

    以上情况还可以。但不能保证总是工作。检查以下链接: How do I render the scrollable regions of a canvas with IViewObject::Draw?

    【讨论】:

      【解决方案4】:

      如果您可以使用 javascript,我建议您使用 phantomjs

      来自http://fcargoet.evolix.net/的示例

      var page    = new WebPage(),
          address = 'http://dev.sencha.com/deploy/ext-4.0.7-gpl/examples/feed-viewer/feed-viewer.html';
      
      page.viewportSize = {
          width  : 800,
          height : 600
      };
      
      // define the components we want to capture
      var components = [{
          output : 'feed-viewer-left.png',
          //ExtJS has a nice component query engine
          selector : 'feedpanel'
      },{
          output : 'feed-viewer-preview-btn.png',
          selector : 'feeddetail > feedgrid > toolbar > cycle'
      },{
          output : 'feed-viewer-collapsed.png',
          //executed before the rendering
          before : function(){
              var panel = Ext.ComponentQuery.query('feedpanel')[0];
              panel.animCollapse = false; // cancel animation, no need to wait before capture
              panel.collapse();
          },
          selector : 'viewport'
      }];
      
      page.open(address, function (status) {
          if (status !== 'success') {
              console.log('Unable to load the address!');
          } else {
              /*
               * give some time to ExtJS to
               *   - render the application
               *   - load asynchronous data
               */
              window.setTimeout(function () {
                  components.forEach(function(component){
                      //execute the before function
                      component.before && page.evaluate(component.before);
                      // get the rectangular area to capture
                      /*
                       * page.evaluate() is sandboxed
                       * so that 'component' is not defined.
                       *
                       * It should be possible to pass variables in phantomjs 1.5
                       * but for now, workaround!
                       */
                      eval('function workaround(){ window.componentSelector = "' + component.selector + '";}')
                      page.evaluate(workaround);
      
                      var rect = page.evaluate(function(){
                          // find the component
                          var comp = Ext.ComponentQuery.query(window.componentSelector)[0];
                          // get its bounding box
                          var box = comp.el.getBox();
                          // box is {x, y, width, height}
                          // we want {top, left, width, height}
                          box.top  = box.y;
                          box.left = box.x;
                          return box;
                      });
                      page.clipRect = rect;
                      page.render(component.output);
                  });
                  // job done, exit
                  phantom.exit();
              }, 2000);
          }
      });
      

      【讨论】:

        猜你喜欢
        • 2011-07-17
        • 1970-01-01
        • 1970-01-01
        • 2011-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多