我想在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));
});
答案 0 :(得分:2)
PhantomJS有两个不同的背景。由于CasperJS建立在PhantomJS之上,因此它具有相同的限制。您只能从页面/ DOM上下文访问DOM。 casper.evaluate()
提供了此访问权限,但您传入其中的函数是沙盒化的,如PhantomJS documentation中所示。
您无法在document.evaluate
之外调用casper.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));
});