var system = require("system");
var page;
// user supplied url
var myurl = system.args[1];
// var myurl = 'https://waffles.ch/';
page = require('webpage').create();
// suppress errors from output
page.onError = function(msg, trace) {};
// 5 seconds
page.settings.resourceTimeout = 5000;
// page.settings.javascriptEnabled = false;
page.open(myurl, function(status) {
//hack for page.open not hooking into phantom.onError
setTimeout(function() {
if (status !== "success") {
console.log(myurl);
phantom.exit();
throw new Error("Unable to access network");
} else {
var pageTitle = myurl.replace(/http.*\/\//g, "").replace("www.", "").split("/")[0];
var filePath = "img/" + pageTitle + '.jpg';
page.render(filePath, {format: 'jpeg', quality: '75'});
console.log(filePath);
phantom.exit();
}
}, 0);
});
使用上面的代码截取屏幕截图适用于大多数网页。 但是,通过控制台或带有网址“https://waffles.ch/”的网络应用程序运行脚本会导致它在page.open上无限挂起(我相信)。
我假设的原因是因为这个URL包含一些不停止运行的JS动画(一架飞机飞过屏幕),它导致Phantom锁定。这是一个已知的错误吗?
我非常确定JS会导致挂起,因为如果我使用page.settings.javascriptEnabled = false;
将其关闭,那么页面的屏幕截图会毫无问题地呈现。
由于显而易见的原因(page.evaluate,重定向等),我无法实际关闭javascript来截取屏幕截图,所以这是我的2个问题。
1。)有没有办法为包含waffles.ch
等动画的网页呈现屏幕截图,而无需关闭javascript?
2。)如果一个网页挂起,在page.open
如何退出幻像并可能还会返回错误?)
非常感谢任何帮助/建议。
幻影版:2.1.1 操作系统:Windows 7 64位。
我尝试过的其他事情。(但仍然挂在上面的网址)
使用try / catch
var system = require("system");
var page;
// user supplied url
var myurl = system.args[1];
var page = require('webpage').create();
page.open(myurl, function (status) {
try {
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
} else {
//do some stuff with the DOM
var pageTitle = myurl.replace(/http.*\/\//g, "").replace("www.", "").split("/")[0];
var filePath = "img/" + pageTitle + '.jpg';
page.render(filePath, {format: 'jpeg', quality: '75'});
console.log(filePath);
phantom.exit();
}
} catch (ex) {
var fullMessage = "\nJAVASCRIPT EXCEPTION";
fullMessage += "\nMESSAGE: " + ex.toString();
for (var p in ex) {
fullMessage += "\n" + p.toUpperCase() + ": " + ex[p];
}
console.log(fullMessage);
}
});
// ******************************
使用waitfor()
功能。
https://github.com/ariya/phantomjs/blob/master/examples/waitfor.js
var system = require("system");
var page;
// user supplied url
var myurl = system.args[1];
var page = require('webpage').create();
// suppress errors from output
page.onError = function(msg, trace) {
console.log("Error occurred" + msg);
phantom.exit();
};
// 5 seconds
page.settings.resourceTimeout = 5000;
page.open(myurl, function (status) {
// Check for page load success
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
} else {
waitFor(function() {
// Check in the page if a specific element is now visible
return page.evaluate(function() {
return $("body").is(":visible");
});
}, function() {
console.log("body is visible");
phantom.exit();
});
}
});
答案 0 :(得分:1)
事实证明在这种情况下无法终止幻影,至少不是自己,但有一种方法可以避免这个问题。
根本原因是phantomJs中requestAnimationFrame
的实现对tweenJs不起作用。通过幻像返回回调的数字是一个UNIX纪元号(但是小数秒),而tweenJs需要一个DOMHighResTimeStamp(就像你从performance.now()得到的那样,从进程开始时的零开始)。纪元号始终远高于补间结束时间,因此每次更新都被视为补间的结束,这会导致TWEEN.update
进入下一个循环,从而导致其阻塞。
修复它的方法是使用performance.now
注入polyfill,包括requestAnimationFrame
pollyfil,以覆盖幻像的page.injectJs
实施。
以下是需要注入的代码(或更好)...
请求动画frame.js
// Include a performance.now polyfill
var now = (function () {
// In node.js, use process.hrtime.
if (this.window === undefined && this.process !== undefined) {
now = function () {
var time = process.hrtime();
// Convert [seconds, microseconds] to milliseconds.
return time[0] * 1000 + time[1] / 1000;
};
}
// In a browser, use window.performance.now if it is available.
else if (this.window !== undefined &&
window.performance !== undefined &&
window.performance.now !== undefined) {
// This must be bound, because directly assigning this function
// leads to an invocation exception in Chrome.
now = window.performance.now.bind(window.performance);
}
// Use Date.now if it is available.
else if (Date.now !== undefined) {
now = Date.now;
}
// Otherwise, use 'new Date().getTime()'.
else {
now = function () {
return new Date().getTime();
};
}
return now
})();
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
// Adapted to shim floating point milliseconds since the page was opened
// https://developers.google.com/web/updates/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision?hl=en
(function() {
var lastTime = 0;
var rAF = window.requestAnimationFrame;
window.requestAnimationFrame = function(callback) {
var currTime = now();
var timeToCall = Math.max(0, 1000/60 - (currTime - lastTime));
var tcb = currTime + timeToCall;
var cbprxy = (function (cb, t) {
return function (discard) {
cb(t)
}
})(callback, tcb);
var id = rAF
? rAF.call(window, cbprxy)
: window.setTimeout(function() { callback(tcb); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if(!window.cancelAnimationFrame)
window.cancelAnimationFrame = clearTimeout
}());
这里是放入幻像外部上下文以注入它的代码......
page.onInitialized = function() {
page.injectJs('request-animation-frame.js');
};
在你的问题的背景下......
/**
* Adjusted by cool.blue on 08-Sep-16.
*/
var system = require('system');
var page;
// user supplied url
var myurl = system.args[1] || 'https://waffles.ch/';
page = require('webpage').create();
// suppress errors from output
page.onError = function(msg, trace) {};
function exitPhantom (message) {
console.log(message)
phantom.exit(message.match("Error:") ? 1 : 0)
}
page.onConsoleMessage = function(message) {
system.stdout.write('> ' + message + '\n')
};
page.onInitialized = function() {
page.injectJs('request-animation-frame.js');
};
// 5 seconds
page.settings.resourceTimeout = 10000;
// page.settings.javascriptEnabled = false;
page.open(myurl, function(status) {
//hack for page.open not hooking into phantom.onError
setTimeout(function() {
if (status !== "success") {
exitPhantom('Error: ' + status);
throw new Error("Unable to access network");
} else {
var pageTitle = myurl.replace(/http.*\/\//g, "").replace("www.", "").split("/")[0];
var filePath = "img/" + pageTitle + '.jpg';
page.render(filePath, {format: 'jpeg', quality: '75'});
console.log(filePath);
exitPhantom(status);
}
}, 1000);
});
在这种情况下,resourceTimeout
功能将按照宣传的方式工作,并防止过长的加载时间,任何使用类似动画技术的页面都可以正常工作。