打开网页并截取屏幕截图。
仅使用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。所以不,它不是时间问题。
答案 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
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解决方案非常感兴趣
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的帮助