Phantom JS :first-child 一半时间返回正确结果?
Phantom JS :first-child returning correct results half the time?
我从 PhantomJS 得到的结果只有一半是正确的。
我正在尝试将生成的飞机俯视图图像保存在页面上
http://www5b.wolframalpha.com/input/?i=planes+overhead+90210
The image I should be getting everytime
我花了很多时间来达到这一点,现在有几天停留在这一点上。似乎没有办法使用 queryselect 或图像,所以这是我能想到的最好的方法。我认为它有效,但结果只有一半的时间有效。
非常感谢任何能为我指明正确方向的人。
虽然缩小到页面区域的屏幕截图会起作用,但航班开销列表经常收缩和扩展 - 因此很难设置包含所有结果的静态大小。
如果 java 脚本(或特别是 PhantomJS)中有一种方法可以使用 select 图像而不是 Id 或 Class 的元素,那将有很大帮助。
我们正在使用此图像覆盖远程天文台的实时 360 摄像机。我们看到很多飞机在成像时经过相机,如果能够知道当前时刻在头顶上方的是什么就好了。
var page = require('webpage').create();
page.viewportSize = {
width : 650,
height : 480
};
page.open('http://www5b.wolframalpha.com/input/?i=planes+overhead+90210', function (status) {
just_wait();
var clipRect = page.evaluate(function () {
return document.querySelector('#answers:first-child').getBoundingClientRect();
});
page.clipRect = {
top : clipRect.top,
left : clipRect.left,
width : clipRect.width,
height : clipRect.height
};
function just_wait() {
setTimeout(function () {
page.render('flightsoverhead.png');
phantom.exit();
}, 3200);
}
});
您看到的问题是因为您没有等待页面加载,因为某些元素是异步加载的。您可以像这样等待一段静态时间:
var page = require('webpage').create();
page.viewportSize = { width: 650, height: 480 };
page.open('http://www5b.wolframalpha.com/input/?i=planes+overhead+90210', function (status) {
setTimeout(function() {
var clipRect = page.evaluate(function(){
return document.querySelector('#Input').getBoundingClientRect();
});
var clipRectResult = page.evaluate(function(){
return document.querySelector('#Result').getBoundingClientRect();
});
page.clipRect = {
top: clipRect.top,
left: clipRect.left,
width: clipRect.width,
height: clipRect.height + clipRectResult.height
};
console.log(JSON.stringify(clipRect));
page.render('flightsoverhead.png');
phantom.exit();
}, 5000);
});
或者你可以使用waitFor()
等待元素加载
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};
var page = require('webpage').create();
page.viewportSize = { width: 650, height: 480 };
page.open('http://www5b.wolframalpha.com/input/?i=planes+overhead+90210', function (status) {
var clipRect;
waitFor(function _check() {
clipRect = page.evaluate(function(){
return {
input: document.querySelector('#Input').getBoundingClientRect(),
result: document.querySelector('#Result').getBoundingClientRect(),
};
});
return clipRect && clipRect.input && clipRect.input.height > 50 && clipRect.result && clipRect.result.height > 50;
}, function _onReady(){
page.clipRect = {
top: clipRect.input.top,
left: clipRect.input.left,
width: clipRect.input.width,
height: clipRect.input.height + clipRect.result.height
};
page.render('flightsoverhead2.png');
phantom.exit();
}, 10000);
});
当您查看标记时:
<section id="answers">
<section id="Input">...</section>
<section id="Result">...</section>
<section id="SkyMap:FlightData">...</section>
</section>
您对 #Input
和 #Result
感兴趣,因此使用 :first-child
是不够的(顺便说一句,#answers:first-child
选择 #answers
本身就是第一个子元素的元素,你想使用 #answers > :first-child
)。您可以将所需的两个元素的尺寸组合在一起以获得正确的 clipRect
.
我从 PhantomJS 得到的结果只有一半是正确的。
我正在尝试将生成的飞机俯视图图像保存在页面上
http://www5b.wolframalpha.com/input/?i=planes+overhead+90210
The image I should be getting everytime
我花了很多时间来达到这一点,现在有几天停留在这一点上。似乎没有办法使用 queryselect 或图像,所以这是我能想到的最好的方法。我认为它有效,但结果只有一半的时间有效。
非常感谢任何能为我指明正确方向的人。
虽然缩小到页面区域的屏幕截图会起作用,但航班开销列表经常收缩和扩展 - 因此很难设置包含所有结果的静态大小。
如果 java 脚本(或特别是 PhantomJS)中有一种方法可以使用 select 图像而不是 Id 或 Class 的元素,那将有很大帮助。
我们正在使用此图像覆盖远程天文台的实时 360 摄像机。我们看到很多飞机在成像时经过相机,如果能够知道当前时刻在头顶上方的是什么就好了。
var page = require('webpage').create();
page.viewportSize = {
width : 650,
height : 480
};
page.open('http://www5b.wolframalpha.com/input/?i=planes+overhead+90210', function (status) {
just_wait();
var clipRect = page.evaluate(function () {
return document.querySelector('#answers:first-child').getBoundingClientRect();
});
page.clipRect = {
top : clipRect.top,
left : clipRect.left,
width : clipRect.width,
height : clipRect.height
};
function just_wait() {
setTimeout(function () {
page.render('flightsoverhead.png');
phantom.exit();
}, 3200);
}
});
您看到的问题是因为您没有等待页面加载,因为某些元素是异步加载的。您可以像这样等待一段静态时间:
var page = require('webpage').create();
page.viewportSize = { width: 650, height: 480 };
page.open('http://www5b.wolframalpha.com/input/?i=planes+overhead+90210', function (status) {
setTimeout(function() {
var clipRect = page.evaluate(function(){
return document.querySelector('#Input').getBoundingClientRect();
});
var clipRectResult = page.evaluate(function(){
return document.querySelector('#Result').getBoundingClientRect();
});
page.clipRect = {
top: clipRect.top,
left: clipRect.left,
width: clipRect.width,
height: clipRect.height + clipRectResult.height
};
console.log(JSON.stringify(clipRect));
page.render('flightsoverhead.png');
phantom.exit();
}, 5000);
});
或者你可以使用waitFor()
等待元素加载
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};
var page = require('webpage').create();
page.viewportSize = { width: 650, height: 480 };
page.open('http://www5b.wolframalpha.com/input/?i=planes+overhead+90210', function (status) {
var clipRect;
waitFor(function _check() {
clipRect = page.evaluate(function(){
return {
input: document.querySelector('#Input').getBoundingClientRect(),
result: document.querySelector('#Result').getBoundingClientRect(),
};
});
return clipRect && clipRect.input && clipRect.input.height > 50 && clipRect.result && clipRect.result.height > 50;
}, function _onReady(){
page.clipRect = {
top: clipRect.input.top,
left: clipRect.input.left,
width: clipRect.input.width,
height: clipRect.input.height + clipRect.result.height
};
page.render('flightsoverhead2.png');
phantom.exit();
}, 10000);
});
当您查看标记时:
<section id="answers">
<section id="Input">...</section>
<section id="Result">...</section>
<section id="SkyMap:FlightData">...</section>
</section>
您对 #Input
和 #Result
感兴趣,因此使用 :first-child
是不够的(顺便说一句,#answers:first-child
选择 #answers
本身就是第一个子元素的元素,你想使用 #answers > :first-child
)。您可以将所需的两个元素的尺寸组合在一起以获得正确的 clipRect
.