获取可靠的网站截图? Phantomjs和Casperjs都在一些网站上返回空屏幕截图

时间:2014-10-22 21:59:43

标签: javascript phantomjs screen-scraping casperjs

打开网页并截取屏幕截图。

仅使用phantomjs :(这是一个简单的脚本,实际上它是他们的文档中使用的示例脚本。http://phantomjs.org/screen-capture.html

var page = require('webpage').create();
page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

问题是,对于某些网站(如github)而言,有趣的是以某种方式检测并且不提供phantomjs并且没有任何内容被渲染。结果是github.png是一个空白的白色png文件。

将github替换为:" google.com"并且您可以按预期获得一个漂亮的(正确的)屏幕截图。

起初我认为这是一个Phantomjs问题所以我尝试通过Casperjs运行它:

casper.start('http://www.github.com/', function() {
    this.captureSelector('github.png', 'body');
});

casper.run();

但我得到与Phantomjs相同的行为。

所以我认为这很可能是用户代理问题。如:Github嗅出Phantomjs并决定不显示页面。所以我将用户代理设置为下方,但仍然无法正常工作。

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36';
page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

然后我尝试解析页面,显然有些网站(再次像github)似乎没有发送任何信息。

使用casperjs我试图打印标题。对于google.com我回来了Google但是对于github.com我回来了bupkis。示例代码:

var casper = require('casper').create();

casper.start('http://github.com/', function() {
    this.echo(this.getTitle());
});

casper.run();  

与上述相同也会在纯幻影中产生相同的结果。

更新

这可能是一个时间问题吗? github只是超级慢吗?我怀疑它,但无论如何都要测试..

var page = require('webpage').create();
page.open('http://github.com', function (status) {
    /* irrelevant */
   window.setTimeout(function () {
            page.render('github.png');
            phantom.exit();
        }, 3000);
});

结果仍然是bupkis。所以不,它不是时间问题。

  1. 有些网站如github阻止幻影?
  2. 我们如何可靠地截取所有网页的屏幕截图?要求快速,无头。

1 个答案:

答案 0 :(得分:26)

经过一段时间的反复,我能够缩小问题的范围。显然,PhantomJS使用sslv3的默认ssl,这会导致github由于ssl握手错误而拒绝连接

phantomjs --debug=true github.js

显示输出:

. . .
2014-10-22T19:48:31 [DEBUG] WebPage - updateLoadingProgress: 10 
2014-10-22T19:48:32 [DEBUG] Network - Resource request error: 6 ( "SSL handshake failed" ) URL: "https://github.com/" 
2014-10-22T19:48:32 [DEBUG] WebPage - updateLoadingProgress: 100 

因此我们可以得出结论,由于github拒绝连接,因此没有采取任何屏幕。伟大的,完美的感觉。因此,让我们将SSL标记设置为--ssl-protocol=any,并且还允许忽略--ignore-ssl-errors=true

的ssl错误
phantomjs --ignore-ssl-errors=true --ssl-protocol=any --debug=true github.js

非常成功!现在正在渲染并正确保存屏幕截图,但调试器向我们展示了TypeError:

TypeError: 'undefined' is not a function (evaluating 'Array.prototype.forEach.call.bind(Array.prototype.forEach)')

  https://assets-cdn.github.com/assets/frameworks-dabc650f8a51dffd1d4376a3522cbda5536e4807e01d2a86ff7e60d8d6ee3029.js:29
  https://assets-cdn.github.com/assets/frameworks-dabc650f8a51dffd1d4376a3522cbda5536e4807e01d2a86ff7e60d8d6ee3029.js:29
2014-10-22T19:52:32 [DEBUG] WebPage - updateLoadingProgress: 72 
2014-10-22T19:52:32 [DEBUG] WebPage - updateLoadingProgress: 88 
ReferenceError: Can't find variable: $

  https://assets-cdn.github.com/assets/github-fa2f009761e3bc4750ed00845b9717b09646361cbbc3fa473ad64de9ca6ccf5b.js:1
  https://assets-cdn.github.com/assets/github-fa2f009761e3bc4750ed00845b9717b09646361cbbc3fa473ad64de9ca6ccf5b.js:1

我手动检查了github主页,看看是否存在TypeError而且它没有。

我的下一个猜测是资产加载速度不够快。 Phantomjs比速度更快的子弹更快!

因此,让我们尝试人为地减慢它,看看我们是否可以摆脱那种TypeError ...

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36';
page.open('http://github.com', function (status) {
   window.setTimeout(function () {
            page.render('github.png');
            phantom.exit();
        }, 3000);
});

那是行不通的......仔细检查一下图像后,很明显有些元素缺失了。主要是一些图标和徽标。

<强>成功吗 部分是因为我们现在至少在早些时候获得了一个屏幕截图,我们没有得到一个东西。

工作完成了吗? 不完全是。需要确定导致TypeError的原因,因为它阻止某些资产加载并扭曲图像。

的其他

尝试使用CasperJS重新创建 - 与PhantomJS相比,debug非常丑陋且难以理解:

casper.start();
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
casper.thenOpen('https://www.github.com/', function() {
    this.captureSelector('github.png', 'body');
});

casper.run();

控制台:

casperjs test --ssl-protocol=any --debug=true github.js

此外,图像缺少相同的图标,但视觉上也会失真。由于CasperJs依赖于Phantomjs,我没有看到将它用于这项特定任务的价值。

如果您想添加我的回答,请分享您的发现。对完美无瑕的PhantomJS解决方案非常感兴趣

更新#1:删除TypeError

@ArtjomB指出Phantomjs在此更新(1.9.7)中不支持js bind当前版本。出于这个原因,他解释说:ArtjomB: PhantomJs Bind Issue Answer

  

TypeError:&#39; undefined&#39;不是函数指的是bind,因为   PhantomJS 1.x并不支持它。 PhantomJS 1.x使用旧的分叉   QtWebkit可与Chrome 13或Safari 5相媲美。较新版本   PhantomJS 2将使用更新的引擎来支持绑定。目前   你需要在page.onInitialized事件处理程序中添加一个垫片:

好的,所以下面的代码将从上面处理我们的TypeError。 (但功能不全,详见下文)

var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36';
page.open('http://github.com', function (status) {
   window.setTimeout(function () {
            page.render('github.png');
            phantom.exit();
        }, 5000);
});
page.onInitialized = function(){
    page.evaluate(function(){
        var isFunction = function(o) {
          return typeof o == 'function';
        };

        var bind,
          slice = [].slice,
          proto = Function.prototype,
          featureMap;

        featureMap = {
          'function-bind': 'bind'
        };

        function has(feature) {
          var prop = featureMap[feature];
          return isFunction(proto[prop]);
        }

        // check for missing features
        if (!has('function-bind')) {
          // adapted from Mozilla Developer Network example at
          // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
          bind = function bind(obj) {
            var args = slice.call(arguments, 1),
              self = this,
              nop = function() {
              },
              bound = function() {
                return self.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments)));
              };
            nop.prototype = this.prototype || {}; // Firefox cries sometimes if prototype is undefined
            bound.prototype = new nop();
            return bound;
          };
          proto.bind = bind;
        }
    });
}

现在上面的代码将为我们提供与之前相同的屏幕截图,并且调试不会显示TypeError,因此从表面看,一切似乎都有效。已经取得了进展。

不幸的是,所有图片图标[徽标等]仍未正确加载。我们看到某种 3W 图标无法确定来自哪里。

感谢@ArtjomB的帮助

enter image description here