保存网页为图片

7
作为一个兴趣项目,我正在探索以编程方式(主要使用C/C++/JavaScript/Java)保存网页(HTML)为图像的方法。到目前为止,我已经遇到了以下几种方法:
1. 获取页面主体的IHTMLElement并使用其查询IHTMLElementRender,然后使用其DrawToDC方法(参考:http://www.codeproject.com/KB/IP/htmlimagecapture.aspx)。但是问题在于它并不适用于所有页面(大多数是嵌入iframe的页面)。
2. 另一种想到的方法是使用某些Web浏览器组件,在页面完全加载后使用BitBlt进行捕捉(参考:http://msdn.microsoft.com/en-us/library/dd183370%28VS.85%29.aspx)。但是问题在于我请求的页面可能比我的屏幕尺寸更长,无法适应Web浏览器组件。
非常感谢任何解决上述问题或提供替代方法的指导和建议。
4个回答

1

终于通过阅读以下两篇文章破解了它:

  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]

以上的方法仍然可以使用,但并不保证始终有效。请查看下面的链接:如何使用IViewObject::Draw渲染画布的可滚动区域?

1
如果您使用Python,有pywebshotwebkit2png。不过它们都有一些依赖关系。
编辑:糟糕,Python不在您首选语言列表中。无论如何,我还是会保留这个答案,因为您说“主要”而不是“专门”。

谢谢kijin..我已经考虑过了,但是为了使用它,我必须学习Python :) - Favonius

1

另一个(有点绕路的)选项是运行像Tomcat这样的服务器,并使用Java调用命令行工具来截取屏幕截图。在Google上搜索“command line screenshot windows”会出现一些看起来不错的可能性。除了运行服务器之外,我不知道从javascript中运行本地可执行文件的好方法。但这种方法可以使它跨浏览器,这是一个优点(当您想要截屏时,只需对脚本进行ajax调用)。

不幸的是,我实际上不知道如何部署war文件。使用Tomcat可能会更麻烦;我提到它是因为Java是首选语言。运行XAMPP并使用此PHP片段将非常简单,您真的不需要学习php:

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

编辑

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


谢谢,你能详细说明一下这里使用Tomcat和Java的用途吗?比如说,我想访问http://stackoverflow.com,那么Tomcat怎么应用呢?Selenium是个不错的选择,我会研究一下的。 - Favonius
其实,我不知道在Tomcat上部署Web应用程序有多复杂。使用XAMPP和PHP片段可能更容易。我编辑了我的答案。 - theazureshadow

0

如果您可以使用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);
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接