fab*_*bbb 24 javascript screen-scraping phantomjs 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();
});
Run Code Online (Sandbox Code Playgroud)
问题是,对于一些网站(如github),足够有趣的是以某种方式检测并且不提供phantomjs并且没有任何东西被渲染.结果是github.png一个空白的白色png文件.
用说:"google.com"替换github,你会得到一个很好的(正确的)截图.
起初我认为这是一个Phantomjs问题所以我尝试通过Casperjs运行它:
casper.start('http://www.github.com/', function() {
this.captureSelector('github.png', 'body');
});
casper.run();
Run Code Online (Sandbox Code Playgroud)
但我得到与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();
});
Run Code Online (Sandbox Code Playgroud)
所以我试图解析页面,显然有些网站(再次像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();
Run Code Online (Sandbox Code Playgroud)
与上述相同也在纯粹的幻影中产生相同的结果.
这可能是一个时间问题吗?github只是超级慢吗?我怀疑它,但无论如何都要测试..
var page = require('webpage').create();
page.open('http://github.com', function (status) {
/* irrelevant */
window.setTimeout(function () {
page.render('github.png');
phantom.exit();
}, 3000);
});
Run Code Online (Sandbox Code Playgroud)
结果仍然是bupkis.所以不,这不是时间问题.
fab*_*bbb 26
经过一段时间的反复,我能够缩小问题的范围.显然,PhantomJS使用默认的ssl sslv3,导致github由于ssl握手错误而拒绝连接
phantomjs --debug=true github.js
Run Code Online (Sandbox Code Playgroud)
显示输出:
. . .
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
Run Code Online (Sandbox Code Playgroud)
因此,我们可以得出结论,没有采用屏幕,因为github拒绝连接.伟大的,完美的感觉.所以让我们设置SSL标志,--ssl-protocol=any并让我们也忽略ssl-errors--ignore-ssl-errors=true
phantomjs --ignore-ssl-errors=true --ssl-protocol=any --debug=true github.js
Run Code Online (Sandbox Code Playgroud)
巨大的成功!屏幕截图现在正在呈现并正确保存,但调试器向我们显示了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
Run Code Online (Sandbox Code Playgroud)
我手动检查了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);
});
Run Code Online (Sandbox Code Playgroud)
这不起作用......仔细检查图像后 - 很明显有些元素缺失了.主要是一些图标和徽标.
成功? 部分是因为我们现在至少在早些时候获得了一个屏幕截图,我们没有得到任何东西.
任务完成? 不完全是.需要确定是什么导致了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();
Run Code Online (Sandbox Code Playgroud)
安慰:
casperjs test --ssl-protocol=any --debug=true github.js
Run Code Online (Sandbox Code Playgroud)
此外,图像缺少相同的图标,但也在视觉上失真.由于CasperJs依赖于Phantomjs,我没有看到使用它来完成这项特定任务的价值.
如果您想添加我的答案,请分享您的发现.对完美无瑕的PhantomJS解决方案非常感兴趣
TypeError@ArtjomB指出Phantomjs bind在此更新(1.9.7)中不支持其当前版本中的js .出于这个原因,他解释说:ArtjomB:PhantomJs绑定问题答案
TypeError:'undefined'不是函数引用bind,因为PhantomJS 1.x不支持它.PhantomJS 1.x使用QtWebkit的旧分支,可与Chrome 13或Safari 5相媲美.较新的PhantomJS 2将使用更新的引擎来支持bind.现在你需要在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;
}
});
}
Run Code Online (Sandbox Code Playgroud)
现在上面的代码将为我们提供一个与之前相同的屏幕截图,并且调试不会TypeError从表面显示,所有内容都可以正常工作.已经取得了进展.
不幸的是,所有图像图标[徽标等]仍未正确加载.我们看到某种3W图标不确定它们来自何处.
感谢@ArtjomB的帮助
| 归档时间: |
|
| 查看次数: |
11888 次 |
| 最近记录: |