PhantomJS 没有执行 JS
PhantomJS is not executing JS
我尝试使用 PhantomJS 制作 www.fallswoodsmith.com 的屏幕截图。我的代码是:
var page = require('webpage').create();
page.viewportSize = { width: 1024, height: 768 };
page.clipRect = {top: 0, left: 0, width: 1024, height: 768};
page.open('http://www.fallswoodsmith.com', function () {
page.render('cache/www.fallswoodsmith.com123567266_1024_768.png', {format: 'png', quality: '10'});
phantom.exit();
});
这个页面只有 JS,所以没有 JS 就没有内容。出于某种原因,PhantomJS 没有执行这个 JS。我还尝试为 page.render()
和 phantom.exit()
设置 5 秒的超时,但这并没有改变什么。如果我在 page.render()
之前执行 console.log(page.content)
,我将获得页面的完整 HTML - 只是没有 JS 所做的更改。
为什么PhantomJS不执行页面的JS?
更新 1:
我添加了以下调试内容:
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};
page.onError = function(msg, trace) {
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
});
}
console.error(msgStack.join('\n'));
};
page.onResourceError = function(resourceError) {
console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
page.onResourceTimeout = function(request) {
console.log('Response (#' + request.id + '): ' + JSON.stringify(request));
};
我的控制台没有 console.log() 输出...
请允许我礼貌地问一下,那个网站是谁制作的?我强烈建议不要以 100% 依赖 JavaScript 的方式构建站点。关闭 JavaScript 和 "loading" 该站点 (www.fallswoodsmith.com) 没有任何结果。压缩。虚无。 zilch。 </rant>
您正在寻找的答案
运行你上面的截图脚本,我得到如下输出:
TypeError: 'undefined' is not a function (evaluating 'joinURL.bind(null, staticServerUrl)')
http://static.parastorage.com/services/santa-versions/1.150.0/main-r.js:353 in wixRenderSite
要解决该问题,您可以 polyfill Function.prototype.bind
(which is missing from PhantomJS 1.x, as per this issue) after the web page object is created but before a URL is loaded (i.e. onInitialized
).
结果:
var page = require('webpage').create();
page.onInitialized = function () {
page.evaluate(function () {
var isFunction = function (obj) {
return typeof obj == 'function' || false;
};
var slice = Array.prototype.slice;
Function.prototype.bind = function bind(obj) {
var args = slice.call(arguments, 1);
var self = this;
var F = function () {};
var bounded = function() {
return self.apply(
this instanceof F ? this : (obj || {}),
args.concat(slice.call(arguments))
);
};
F.prototype = this.prototype || {};
bounded.prototype = new F();
return bounded;
};
});
};
page.open('http://www.fallswoodsmith.com', function () {
setTimeout(function screenshot() {
page.render('WORKS.png', {
format: 'png',
quality: '10',
});
phantom.exit();
}, 10 * 1000);
});
为什么要等10秒再截图?好吧,由于该站点完全依赖于 JS,因此没有明显的事件(我能想到的)等待指示页面加载。你的旅费可能会改变。根据需要增加或减少超时。
注意:上面的输出文件名是WORKS.png
.
PhantomJS 版本
以上示例已经过测试并适用于 PhantomJS 1.9.7。该脚本似乎也适用于 PhantomJS 1.9.8,但 1.9.8 具有 this issue (Unsafe JavaScript attempt to access frame in 1.9.8),虽然已修复,但不属于任何版本并导致以下错误输出:
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
视口大小
默认情况下,渲染图像将是整页屏幕截图。要修复视口大小,您可以在脚本顶部重新添加以下内容:
page.viewportSize = {
width: 1024,
height: 768
};
page.clipRect = {
top: 0,
left: 0,
width: 1024,
height: 768
};
填充.bind
在 MDN, doesn't seem to work without a bit of modification, but that, combined with the underscore.js source code and this answer 上找到的 polyfill 导致了上述结果。
自 2.1 版以来,phantomjs 已将 polyfill 包含到发行版的 javascript 引擎中。试试他们的 latest version.
我尝试使用 PhantomJS 制作 www.fallswoodsmith.com 的屏幕截图。我的代码是:
var page = require('webpage').create();
page.viewportSize = { width: 1024, height: 768 };
page.clipRect = {top: 0, left: 0, width: 1024, height: 768};
page.open('http://www.fallswoodsmith.com', function () {
page.render('cache/www.fallswoodsmith.com123567266_1024_768.png', {format: 'png', quality: '10'});
phantom.exit();
});
这个页面只有 JS,所以没有 JS 就没有内容。出于某种原因,PhantomJS 没有执行这个 JS。我还尝试为 page.render()
和 phantom.exit()
设置 5 秒的超时,但这并没有改变什么。如果我在 page.render()
之前执行 console.log(page.content)
,我将获得页面的完整 HTML - 只是没有 JS 所做的更改。
为什么PhantomJS不执行页面的JS?
更新 1: 我添加了以下调试内容:
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};
page.onError = function(msg, trace) {
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
});
}
console.error(msgStack.join('\n'));
};
page.onResourceError = function(resourceError) {
console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
page.onResourceTimeout = function(request) {
console.log('Response (#' + request.id + '): ' + JSON.stringify(request));
};
我的控制台没有 console.log() 输出...
请允许我礼貌地问一下,那个网站是谁制作的?我强烈建议不要以 100% 依赖 JavaScript 的方式构建站点。关闭 JavaScript 和 "loading" 该站点 (www.fallswoodsmith.com) 没有任何结果。压缩。虚无。 zilch。 </rant>
您正在寻找的答案
运行你上面的截图脚本,我得到如下输出:
TypeError: 'undefined' is not a function (evaluating 'joinURL.bind(null, staticServerUrl)')
http://static.parastorage.com/services/santa-versions/1.150.0/main-r.js:353 in wixRenderSite
要解决该问题,您可以 polyfill Function.prototype.bind
(which is missing from PhantomJS 1.x, as per this issue) after the web page object is created but before a URL is loaded (i.e. onInitialized
).
结果:
var page = require('webpage').create();
page.onInitialized = function () {
page.evaluate(function () {
var isFunction = function (obj) {
return typeof obj == 'function' || false;
};
var slice = Array.prototype.slice;
Function.prototype.bind = function bind(obj) {
var args = slice.call(arguments, 1);
var self = this;
var F = function () {};
var bounded = function() {
return self.apply(
this instanceof F ? this : (obj || {}),
args.concat(slice.call(arguments))
);
};
F.prototype = this.prototype || {};
bounded.prototype = new F();
return bounded;
};
});
};
page.open('http://www.fallswoodsmith.com', function () {
setTimeout(function screenshot() {
page.render('WORKS.png', {
format: 'png',
quality: '10',
});
phantom.exit();
}, 10 * 1000);
});
为什么要等10秒再截图?好吧,由于该站点完全依赖于 JS,因此没有明显的事件(我能想到的)等待指示页面加载。你的旅费可能会改变。根据需要增加或减少超时。
注意:上面的输出文件名是WORKS.png
.
PhantomJS 版本
以上示例已经过测试并适用于 PhantomJS 1.9.7。该脚本似乎也适用于 PhantomJS 1.9.8,但 1.9.8 具有 this issue (Unsafe JavaScript attempt to access frame in 1.9.8),虽然已修复,但不属于任何版本并导致以下错误输出:
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
视口大小
默认情况下,渲染图像将是整页屏幕截图。要修复视口大小,您可以在脚本顶部重新添加以下内容:
page.viewportSize = {
width: 1024,
height: 768
};
page.clipRect = {
top: 0,
left: 0,
width: 1024,
height: 768
};
填充.bind
在 MDN, doesn't seem to work without a bit of modification, but that, combined with the underscore.js source code and this answer 上找到的 polyfill 导致了上述结果。
自 2.1 版以来,phantomjs 已将 polyfill 包含到发行版的 javascript 引擎中。试试他们的 latest version.