我正在尝试使用getElementXPath function from Firebug在CasperJS中工作,但我似乎找不到合适的地方来调用它来工作。这是我到目前为止,它只适用于已经有“id”标签的对象,但这没有多大帮助,因为我使用XPath代替id(大多数对象没有id)
casper.then(function () {
var Element = this.evaluate(function(){
var elm = document.querySelector('[class="h4"]');
return getElementXPath(elm); //Set 1
//return elm; //Set 2
});
console.log('xpath: '+ Element); //Set 1
//console.log('xpath: '+ getElementXPath(Element)); //Set 2
});
Set 1始终输出“xpath:null”
如果元素已经具有“id”标记,则Set 2仅输出正确的路径。 “xpath:// * [id =”button“]”
Set 2否则将输出最后一个标签,即“xpath:/ a”或“xpath:/ span”
这是来自Firebug的getElementXPath函数,我刚刚粘贴在我的JS文件的顶部。
function getElementXPath(element)
{
if (element && element.id)
return '//*[@id="' + element.id + '"]';
else
return getElementTreeXPath(element);
};
function getElementTreeXPath(element)
{
var paths = [];
// Use nodeName (instead of localName) so namespace prefix is included (if any).
for (; element && element.nodeType == Node.ELEMENT_NODE; element = element.parentNode)
{
var index = 0;
var hasFollowingSiblings = false;
for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
{
// Ignore document type declaration.
if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
continue;
if (sibling.nodeName == element.nodeName)
++index;
}
for (var sibling = element.nextSibling; sibling && !hasFollowingSiblings;
sibling = sibling.nextSibling)
{
if (sibling.nodeName == element.nodeName)
hasFollowingSiblings = true;
}
var tagName = (element.prefix ? element.prefix + ":" : "") + element.localName;
var pathIndex = (index || hasFollowingSiblings ? "[" + (index + 1) + "]" : "");
paths.splice(0, 0, tagName + pathIndex);
}
return paths.length ? "/" + paths.join("/") : null;
};
答案 0 :(得分:1)
当您收听"page.error"
事件时,您会看到类似
错误:ReferenceError:找不到变量:getElementXPath
这与您在页面中包含该代码的方式有关。以下完整脚本适用于我:
var casper = require('casper').create();
// http://docs.casperjs.org/en/latest/events-filters.html#page-error
casper.on("page.error", function(msg, trace) {
this.echo("Error: " + msg);
// maybe make it a little fancier with the code from the PhantomJS equivalent
});
casper.start('http://example.com');
casper.then(function() {
this.evaluate(function(){
window.getElementXPath = function(element)
{
if (element && element.id)
return '//*[@id="' + element.id + '"]';
else
return getElementTreeXPath(element);
};
function getElementTreeXPath(element)
{
var paths = [];
// Use nodeName (instead of localName) so namespace prefix is included (if any).
for (; element && element.nodeType == Node.ELEMENT_NODE; element = element.parentNode)
{
var index = 0;
var hasFollowingSiblings = false;
for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
{
// Ignore document type declaration.
if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
continue;
if (sibling.nodeName == element.nodeName)
++index;
}
for (var sibling = element.nextSibling; sibling && !hasFollowingSiblings;
sibling = sibling.nextSibling)
{
if (sibling.nodeName == element.nodeName)
hasFollowingSiblings = true;
}
var tagName = (element.prefix ? element.prefix + ":" : "") + element.localName;
var pathIndex = (index || hasFollowingSiblings ? "[" + (index + 1) + "]" : "");
paths.splice(0, 0, tagName + pathIndex);
}
return paths.length ? "/" + paths.join("/") : null;
};
});
this.echo(this.evaluate(function(){
return getElementXPath(document.querySelector("a"));
}));
});
casper.run();
输出:
/html/body/div/p[2]/a
诀窍是在页面上下文中使getElementXPath
在全局范围内可用。通过在window.getElementXPath
上设置变量,可以轻松完成此操作。