casperJS如何在从web收集数据时单击表中的多个链接/.click()不起作用?

时间:2013-04-23 04:01:24

标签: javascript click screen-scraping casperjs

我想使用CasperJS抓取一些网络数据。数据位于表格中,每行中都有一个链接,指向包含更多详细信息的页面。在脚本中有一个循环遍历所有表行。我希望Casper单击该链接,在子页面上收集数据并返回一个历史记录,以处理下一个表行。问题是click()不起作用,我不知道为什么。有没有什么办法解决这一问题 ? (注意:jref函数viewContact由href调用)

以下是代码:

var employee = {
    last_name: "",
    first_name: "",
    position: "",
    department: "",
    location: "",
    email: "",
    phone: "",
    twitter: ""
};

var employees = [];
var result_number = 50;
var start_url = 'https://www.jigsaw.com/SearchContact.xhtml?companyId=489781&orderby=0&order=0&opCode=paging&mode=0&estimatedCount=126&dead=false&rpage=1&rowsPerPage=200';

var casper = require('casper').create({
    javascriptEnabled: true
});

casper.start(start_url, function() {
    var js = this.evaluate(function() {
    return document;
});

     for (var i = 1; i <= result_number; i++)
     {        
        // j stands for three neighbour td columns containing: 
        // position, name+link, location

        employee.position = this.getHTML('#sortableTable tr:nth-child(' + i + ') td:nth-child(3) span');

        // click link and get other data
        this.click('#sortableTable tr:nth-child(' + i + ') td:nth-child(4) span a');
            employee.first_name = this.getHTML('#sortableTable tr:nth-child(' + i + ') td:nth-child(4) span a');

        //collect data
        this.waitForSelector('#firstname', function() {
            employee.first_name = this.getHTML('#firstname');
        });

        this.waitForSelector('#lastname', function() {
            employee.last_name = this.getHTML('#lastname');
        });
        this.waitForSelector('#state', function() {
            employee.department = this.getHTML('#state');
        });
        this.waitForSelector('#email', function() {
            employee.email = this.getHTML('#email');
        });
        this.waitForSelector('#phone', function() {
            employee.phone = this.getHTML('#phone');
        });

        //get back to previous page
        this.back();

        employee.location = this.getHTML('#sortableTable tr:nth-child(' + i + ') td:nth-child(5) span');

        this.echo('\n\n Employee number: ' + i + " :\n");
        this.echo('first name : ' + employee.first_name);
        this.echo('last name  : ' + employee.last_name);
        this.echo('position   : ' + employee.position);
        this.echo('department : ' + employee.department);
        this.echo('location   : ' + employee.location);
        this.echo('email      : ' + employee.email);
        this.echo('phone      : ' + employee.phone);

}

});

casper.run();

2 个答案:

答案 0 :(得分:1)

我在这里看到两件需要纠正的事情。首先,代码中的for循环似乎不在任何casperjs方法的范围内。

此:

for (var i = 1; i <= result_number; i++)

它应该在casper.then方法内。我注意到你有结束括号,所以也许你已经通过复制方式贴出代码了。

其次,最重要的是,您要与之互动的tr:nth-child(' + i + ')将无法以这种方式运作。我不知道为什么,但它似乎没有直接起作用。我试过做同样的事情。我的解决方案是首先将i转换为字符串而不是像这样的数字:

pageturn = pageturn + 1;
// Collect <td> contents on each page.
var pageturnString = pageturn.toString();
var linknum = 'a.SomeLinkClass:nth-child('+pageturnString+')';

在我的情况下,我使用它来点击更改页面,无论哪种方式,您必须在第一个方法内的this.then()方法内封装与所述css选择器的交互,然后第二个子方法执行for循环的其余部分。

示例:

casper.each(pagecount, function() {
    this.then(function() {
        pageturn = pageturn + 1;
        // Collect <td> contents on each page.
        var pageturnString = pageturn.toString();
        var linknum = 'a.SomeLinkClass:nth-child('+pageturnString+')';
    });

    this.then(function() {
        //Now run for loop here. 
    });
 });

如果你没有在this.then()方法中将css选择器结构封装在下一个方法中之前使用它,那么它将不起作用。我不知道为什么,但这就是交易。在我的代码中,pagecount可能会被用来代替你的for循环,但我会把它留给你。

答案 1 :(得分:0)

我有一个页面,我在Casper中看到了这个:

[debug] [phantom] Mouse event 'mousedown' on selector: tr:nth-child(2) a CasperError: Cannot dispatch mousedown event on nonexistent selector: tr:nth-child(2) a

由于此错误是由存在的失败引起的,它依赖于querySelectorAll,我已经玩过它并发现以下内容将x2设置为null(尽管x1不为null):

this.evaluate(function() {
    var x1 = document.querySelector('tr:nth-child(2) a');
    var x2 = document.querySelector('tr:nth-child(2) a');
    alert(x1 + ', ' + x2);
});

它似乎取决于有一行不包含<a>,正如您在标题行中找到的那样。这是一个测试页面:

http://jsfiddle.net/GKb2g/4/

我希望在找到原因之后回复这里,但与此同时,你最好使用selectXPath选择器。