我是网络开发的新手,任务是找到网页上的所有元素(例如,我想在亚马逊上找到所有元素,包括页眉,页脚,导航栏等),然后获取所有这些的位置和大小。(包括高度,宽度,顶部,底部,左侧,右侧等)我尝试使用CasperJS和PhantomJS来完成它,这是我的代码:
casper.start('http://www.amazon.com/s?url=search-alias=aps&field-keywords=watches', function(){
});
var objarr = [];
casper.then(function(){
var tmp = this.evaluate(function() {
return document.getElementsByTagName("html")[0]; //get the html and traverse all it children
}
traverseDOMTree(tmp);
for (var i = 0; i < objarr.length; i++){
var isvalid = judge(objarr[i]); //judge whether the elemnet is null.
console.log(i+1);
if (isvalid && i != 0) {
console.log(objarr[i].textContent);
}
}
});
function traverseDOMTree(root) //traverse function
{
if (root)
{
for (var i = 0; i < root.childNodes.length; i++){
objarr.push(root.childNodes[i]);
traverseDOMTree(root.childNodes[i]);
}
}
}
function judge(obj){
if (obj == null) {
console.log("The object is NULL");
return false;
}
//If it is not null, get its location and height with width
console.log("___________________________");
console.log("The offsetTop is ", obj.offsetTop);
console.log("The offsetLeft is ", obj.offsetLeft);
console.log("The height is", obj.clientHeight);
console.log("The width is", obj.clientWidth);
}
所以我的方法首先得到DOM树的根,即document.getElementsByTagId("html")[0]
。然后我遍历它的所有子节点并将我找到的所有元素放入一个数组中。但是,这里有几个问题:
我已经调试并尝试了很长时间的不同方式,但我仍然无法成功。我想我需要将我的遍历函数放入casper.evaluate()
,但是关于如何在网络上使用它的教程太少了。那么有没有人可以帮我找到一个可行的方法呢?
答案 0 :(得分:1)
CasperJS构建于PhantomJS之上,并继承了其中一些缺点,如两个不同的上下文。您只能通过沙盒casper.evaluate()
函数访问DOM(页面上下文)。它不能使用在外部定义的变量,并且您传入或传出的所有内容都必须是基元。 DOM节点不是基元。请参阅文档(page.evaluate()
):
注意:
evaluate
函数的参数和返回值必须是一个简单的原始对象。经验法则:如果它可以通过JSON序列化,那就没关系了。闭包,函数,DOM节点等将不工作!
这意味着您必须在页面上下文中执行所有操作,因为您直接在这些DOM节点上工作。您可以在完成遍历时将结果传递出页面上下文。
或者您可以简单地移动页面上下文中的所有内容并注册到&#34; remote.message&#34;事件:
casper.on("remote.message", function(msg){
this.echo("remote> " + msg);
});
casper.then(function(){
this.evaluate(function() {
var tmp = document.getElementsByTagName("html")[0]; //get the html and traverse all it children
var objarr = [];
traverseDOMTree(tmp);
for (var i = 0; i < objarr.length; i++){
var isvalid = judge(objarr[i]); //judge whether the elemnet is null.
console.log(i+1);
if (isvalid && i != 0) {
console.log(objarr[i].textContent);
}
}
function traverseDOMTree(root) //traverse function
{
if (root)
{
for (var i = 0; i < root.childNodes.length; i++){
objarr.push(root.childNodes[i]);
traverseDOMTree(root.childNodes[i]);
}
}
}
function judge(obj){
if (obj == null) {
console.log("The object is NULL");
return false;
}
//If it is not null, get its location and height with width
console.log("___________________________");
console.log("The offsetTop is ", obj.offsetTop);
console.log("The offsetLeft is ", obj.offsetLeft);
console.log("The height is", obj.clientHeight);
console.log("The width is", obj.clientWidth);
return true;
}
}
});
答案 1 :(得分:0)
这似乎是最简单的方法,而且我不确定你是否会以某种方式限制你如何做到这一点,但我会在普通的javascript中这样做:
var allElements = document.getElementsByTagName("*");
var element, index = 0, length = allElements.length;
for ( ; index < length; index++) {
element = allElements[index];
// get whatever information you want from the element
}
答案 2 :(得分:0)
最简单的方法就是获取所有元素:
document.getElementsByTagName("*");
但是如果你想用递归来实现它:
function traverse(node, elems){
if(node){
elems.push(node)
var childs = node.childNodes;
for(var i=0;i<childs.length;i++){
traverse(childs[i],elems)
}
}
}
domElements = []
traverse(document.getElementsByTagName("html")[0], domElements)
console.log(domElements)