CasperJS - 如何从数组中为每个页面保存一些数据?

CasperJS - How to save some data for each page from an array?

我正在尝试使用 CasperJS 抓取网站,但我 运行 遇到了问题。

在第一页中,我收集了我想要抓取的链接,并使用 getLinks() 函数将它们保存到一个数组中 - 这很有效。

然后我想从这个数组中抓取每个页面(我让这部分工作)并且我想从每个页面中获取一些细节。

我的代码如下(修剪了 casper 启动和登录等工作内容):

// Casper start here, and some login stuff, all these are working fine so I removed them to have a light example

// ....
// ....
// ....

// Function for saving members to an array
function getLinks() {
    var links = document.querySelectorAll(".member_name_and_title");
    return Array.prototype.map.call(links, function(link) {
        return link.childNodes[1].childNodes[1].href
    });
}

casper.then(function() {
    // Aggregate results 
    links = this.evaluate(getLinks);

    casper.each(links, function (self, link) {
        self.thenOpen(link, function () {

            var details = this.evaluate(function(){
                document.getElementsByClassName('member_name')[0].textContent;
            });

            // Grab details for each member
            var data = details + " - " + link;

            // Save data
            var fs = require('fs');
            fs.write('results/output.txt', JSON.stringify(data, null, '  '), 'aw');

        });
    });

});

// Casper run
casper.run(function() {
    this.exit();
});

问题是 details var 将 return 为 null,所以最终的 output.txt 将类似于:

"null - domain.com/link1"
"null - domain.com/link2"
"null - domain.com/link3"
"null - domain.com/link4"
"null - domain.com/link5"

link var 工作正常但 details var 为 returning null。

当我在浏览器控制台中访问数组中的任何 url(例如:domain.com/link1)和 运行 document.getElementsByClassName('member_name')[0].textContent 时,它 return 是值正确,所以我确定定位没问题。

我不确定自己遗漏了什么或做错了什么。任何帮助将非常感激。谢谢!

尝试添加一个 return,如下所述:

var details = this.evaluate(function(){
    return document.getElementsByClassName('member_name')[0].textContent;
});

编辑:

这对我有用。我的代码设置如下:

var casper = require('casper').create();

function getLinks() {
    var matchedLinks = document.querySelectorAll(".member_name_and_title");
    return Array.prototype.map.call(matchedLinks, function(link) {
        return link.href;
    });
}

casper.start('http://localhost:8080');

casper.then(function() {
    // Aggregate results 
    links = this.evaluate(getLinks);

    casper.each(links, function (self, link) {

        // INSPECT: Check if it shows the correct link here.
        self.echo('Opening link:' + link);

        self.thenOpen(link, function () {

            var details = this.evaluate(function(){
                // INSPECT: Make sure to 'return' the text content.
                return document.getElementsByClassName('member_name')[0].textContent;
            });

            // Grab details for each member
            var data = details + " - " + link;

            // INSPECT: Check if the data is correct.
            self.echo(data);

            // Save data
            var fs = require('fs');
            fs.write('results/output.txt', JSON.stringify(data, null, '  '), 'aw');
        });
    });
});


casper.run(function(){
    this.exit();
});

我的html个文件如下:

index.html

<!DOCTYPE html>
<html>
<head>
<title>Hello CasperJs</title>
</head>
<body>

<a href="page1.html" class="member_name_and_title">Page 1</a>
<a href="page2.html" class="member_name_and_title">Page 2</a>
<a href="page3.html" class="member_name_and_title">Page 3</a>
<a href="page4.html" class="member_name_and_title">Page 4</a>

</body>
</html>

page1.html

<!DOCTYPE html>
<html>
<head>
<title>Page 1 Title</title>
</head>
<body>

<p class="member_name">Page 1 Text</p>

</body>
</html>

page2.html、page3.html 和 page4.html 的类似 HTML 标记。我的 http 服务器 运行 在 8080 端口。

我的控制台输出如下:

Opening link:http://localhost:8080/page1.html
Opening link:http://localhost:8080/page2.html
Opening link:http://localhost:8080/page3.html
Opening link:http://localhost:8080/page4.html
Page 1 Text - http://localhost:8080/page1.html
Page 2 Text - http://localhost:8080/page2.html
Page 3 Text - http://localhost:8080/page3.html
Page 4 Text - http://localhost:8080/page4.html

我正在使用 casperjs 1.1.3 和 phantomjs 2.1.1。

你能更新你的代码并分享你的控制台输出和包版本吗?

好吧,我最终弄明白了,完全是菜鸟错误...查询是正确的问题是由页面加载引起的,或者更好的说法是在实际查询之前未加载数组中的链接运行。

为了测试这一点,我在 self.thenOpen 函数中使用了 captureSelection() 来捕获页面打开时的状态,但就在收集数据之前。

this.captureSelector('1.jpg', '#page');

我立即注意到页面未完全加载,因此 return document.querySelector('.member_name.').textContent; 返回 null

为了解决这个问题,我添加了 1.5 秒的等待时间,如下所示:

casper.wait(1500, function() {
  var details = this.evaluate(function(){
    return document.querySelector('.member_name').textContent;
  });
});

新手错误,但将来可能会帮助其他人。