创建数组CasperJS时出现解析错误

时间:2014-08-19 04:06:11

标签: javascript arrays xpath phantomjs casperjs

我试图在网站上抓取多个属性。我打算将它们加载到一个数组中,然后将该数组加载到我服务器上的数据库中的表中。

我尝试创建函数getInfo()并将每个XPath属性加载到数组中(如果这是人们的建议,我可以加载到表中)。我在casper.repeat步骤中将该函数调用了5次。我得到一个解析错误。我不知道这里出了什么问题,因为这是我设置数组来抓取URL并将它们添加到数组中的方法(我在手册中找到):Now let’s scrape Google!

非常感谢任何见解。

代码:

var links = [];
var utils = require('utils');
var casper = require('casper').create();
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36');

function getInfo() {
    var info = document.querySelectorAll(fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[3]/span[1]/span[2]/a)))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[2]/h2/text()))
    + ', ' + fetchText((x()))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[4]/ul/li/span[2]/a)))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[2]/h2/span)))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[5]/div[2]/ul/li[5]/span[2]/a)))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[5]/div[2]/ul/li[1]/span[2])))
    + ', ' + fetchText((x(//*[@id="key"]))
    + ', ' + fetchText((x()))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[5]/div[2]/ul/li[2]/span[2])))
    + ', ' + fetchText((x(//*[@id="body"]/div[1]/ul[1]/li[5]/div[2]/ul/li[6]/span[2]/span[2]/a)))
    + ', ' + fetchText((x())));
    return Array.prototype.map.call(info, function());
}


// This was changed.
casper.repeat(5, function() {
    this.thenOpen(bURL + links[i], function() {
        this.wait(3000);
        info = info.concat(this.evaluate(getInfo));

    });
i++;
}).run();

1 个答案:

答案 0 :(得分:0)

您的代码存在多个问题。

1。解析错误

您看到的解析错误是这一行:

return Array.prototype.map.call(info, function());

至少应该是

return Array.prototype.map.call(info, function(){});

<击> 2。未定义的错误

对问题进行了编辑,以便此部分不再有意义。

这可能是一个错字,但这一行:

links = links.concat(this.evaluate(getLinks));

应该是

links = links.concat(this.evaluate(getInfo));

因为代码中没有getLinks函数。

<击> 3。增量问题

对问题进行了编辑,以便此部分不再有意义。

这样编写,你将以初始增量打开同一页5次,因为你增加了thenOpen回调内部的增量。 CasperJS本质上是异步的,您只计划步骤(如thenOpen调用)。

casper.repeat(5, function() {
    this.thenOpen(googleSearch + '&start=' + increment, function() { ... });
    increment += 10;
}).run();

4。异步/同步问题

您的wait(3000)没有做任何事情,因为它是异步步骤函数,后跟同步evaluateconcat。步骤函数将在当前步骤结束时执行(此处为thenOpen),但会立即执行同步函数。您可以使用then的{​​{1}}回调来实现同步功能。所有wait和所有then*函数都是异步步骤函数。

wait*

5。 XPath不是正则表达式

XPath表达式不像正则表达式那样是javascript的原生表达式。没有XPath对象。 XPath是字符串,因此您需要引用它们。此

this.thenOpen(googleSearch + '&start=' + increment, function() {
    this.wait(3000, function(){
        // aggregate results for the 'BP' search
        links = links.concat(this.evaluate(getLinks));
    });
});

必须是

x(//*[@id="key"])

同样,x('//*[@id="key"]') 不是有效的XPath。

必须引用它,因为在字符串之外以x("")开头的所有内容都是javascript中的注释。如果你做//,你会得到很多未公开的括号。这就是XPath表示为字符串的原因。

6。页面上下文

现在你的脚本了。据我所知,你想从页面中获取一些文本并将它们作为数组发送到某个地方。

您在fetchText(x(//comment))中使用document.querySelectorAll表示getInfo在页面上下文中执行(使用getInfo),因为没有{{1}这样的内容在页面上下文之外。由于页面上下文执行是沙箱化的,因此您无法使用大多数CasperJS函数。只有__utils__被注入页面上下文。 evaluate不是其中之一,XPath实用程序document也是如此,您必须将其添加到脚本的顶部:

fetchText

另一个奇怪的事情是你想要在x中使用所选文本,这只是因为实际CSS选择器的文本可能没有,因为你正在刮取谷歌搜索。

接下来是

var x = require('casper').selectXPath;

将返回document.querySelectorAll值的数组。

解决方案:

您不需要此页面上下文。你会在外面完成这个:

return Array.prototype.map.call(info, function(){});