【问题标题】:What's wrong with my XPath in the CasperJS?我在 CasperJS 中的 XPath 有什么问题?
【发布时间】:2014-02-02 19:01:08
【问题描述】:

我想获取link 中的日期信息,所以我使用的是CasperJS。我分析了日期的XPath:

//*[@id="contentblock"]/td/table[3]/tbody/tr[position()>=3]/td[1]/div

我的 casperJS 脚本如下:

var casper = require('casper').create({
    clientScripts: ["includes/jquery-1.10.2.min.js"]
});
var x = require('casper').selectXPath;

var myear = casper.cli.get(0);
var mmon  = casper.cli.get(1);
var stk_no = casper.cli.get(2);

casper.start('http://www.twse.com.tw/en/trading/exchange/STOCK_DAY/STOCK_DAYMAIN.php', function() {
    this.fill("form[name='date_form']", {
        'myear' : myear,
        'mmon'  : mmon,
        'STK_NO': stk_no
    },true);
});


casper.waitForUrl(/Report/,function() {
    var xPathRes = document.evaluate ( '//*[@id="contentblock"]/td/table[3]/tbody/tr[position()>=3]/td[1]/div', document, null, 0, null);
    this.echo(xPathRes);
    var nodes = xPathRes.iterateNext();
    this.echo(nodes);
    while (nodes)
    {
        this.echo(nodes);
        this.echo(nodes.innerHTML);
        nodes=xPathRes.iterateNext();
    }
});

casper.run();

用命令行

casperjs mytest.js 2014 1 9921

我的脚本给了我回复:

[object XPathResult]
null

xPathRes.iterateNext() 似乎返回了 null,这意味着没有匹配的 xpath。我不确定我的 XPath 和脚本有什么问题。谁能给我一些关于这个问题的提示?

我已经尝试过 XPath:

var xPathRes = document.evaluate('//*', document, null, 0, null);
this.echo(xPathRes);
var nodes = xPathRes.iterateNext();
this.echo(nodes);
while (nodes)
{
    this.echo(nodes.tagName);
    nodes=xPathRes.iterateNext();
}

结果是

[object XPathResult]
[object HTMLHtmlElement]
HTML
HEAD
BODY

我认为它会给出 html 中的每个元素。

再试一次:

var xPathRes = document.evaluate('//*[@id="contentblock"]', document, null, 0, null);
this.echo(xPathRes);
var nodes = xPathRes.iterateNext();
this.echo(nodes);
while (nodes)
{
    this.echo(nodes.tagName);
    nodes=xPathRes.iterateNext();
}

结果是

[object XPathResult]
null

它似乎没有匹配任何东西。这很奇怪,因为如果我用

转储 html,带有 id=contentblock 的元素确实存在
this.debugHTML();

下面使用 CasperJS API 的代码有效。但使用 document.evaluate 失败。这很奇怪。我不知道我应该如何调试。

var x = require('casper').selectXPath;
casper.waitForUrl(/Report/,function() {
    this.test.assertExists(x('//*[@id="contentblock"]/td/table[3]'), 'the element exists');
    this.echo(this.getHTML( x('//*[@id="contentblock"]/td/table[3]/tbody/tr[3]/td[1]/div') ,true));
});

【问题讨论】:

  • 您尝试过逐步测试 XPath 吗?应该很容易找到它停止返回任何东西的点。
  • 我已经尝试了一些 xpaths 作为我添加的描述。很奇怪 '//*[@id="contentblock"]' 不起作用。
  • 您尝试抓取的部分网页是动态生成的。也许那已经失败了。尝试打开调试和/或输出 casper 看到的网页 HTML,以便您查看。
  • 实际上我已经用 this.debugHTML(); 转储了 HTML。所以我想我输出网页 HTML。我不知道那里发生了什么。
  • 我很茫然。我唯一要推荐的是从x("/*") 开始,然后是x("/html")x("//*[@id]")x("//*[@id] > ''") 等等,一次向XPath 表达式添加一个特性。当然也可以在不同的机器/不同的网页上进行测试。

标签: javascript dom xpath phantomjs casperjs


【解决方案1】:

PhantomJS 有两个不同的上下文。由于 CasperJS 是建立在 PhantomJS 之上的,因此它具有相同的限制。您只能从页面/DOM 上下文访问 DOM。 casper.evaluate() 提供此访问权限,但您传递给它的函数是沙盒化的,如 PhantomJS documentation 中所示。

您不能在casper.evaluate() 之外调用document.evaluate,因为document 在页面上下文之外没有任何意义。我不知道为什么 document 甚至存在于 casper 上下文中,因为它什么都不做。实际上,外部上下文有一个仅包含 <html><head></head><body></body></html> 的虚拟页面,它解释了您看到的有限结果。

如果你将它包装在casper.evaluate 中,那么你就不能再将 DOM 元素传递给 casper 上下文,因为只能传入和传出原始对象。如果你想访问元素,你可以使用casper.getElementsInfo,这取决于你想用它做什么。

casper.waitForUrl(/Report/,function() {
    var xPathRes = this.getElementsInfo('//*[@id="contentblock"]/td/table[3]/tbody/tr[position()>=3]/td[1]/div');
    xPathRes.forEach(function(element, index) {
        this.echo(element);
        this.echo(element.html);
    });
});

你也可以在页面上下文中做你的事情,但是你必须记住你可以在页面中进行什么样的表示。

casper.waitForUrl(/Report/,function() {
    var elements = this.evaluate(function(){
        var xPathRes = document.evaluate ( '//*[@id="contentblock"]/td/table[3]/tbody/tr[position()>=3]/td[1]/div', document, null, 0, null);
        var collectHTML = [];
        var nodes = xPathRes.iterateNext();
        while (nodes)
        {
            collectHTML.push(nodes.innerHTML);
            nodes = xPathRes.iterateNext();
        }
        return collectHTML;
    });
    this.echo(JSON.stringify(elements));
});

【讨论】:

    猜你喜欢
    • 2012-09-10
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多