Javascript 在递归方法中将数组设置为null

Javascript 在递归方法中将数组设置为null,javascript,phantomjs,casperjs,Javascript,Phantomjs,Casperjs,我正在尝试使用CasperJS编写一个spider,用于解析页面和提取相关链接。该网站以文件和文件夹的分层视图为特色。我已经编写了一个递归方法来执行文件结构的导航,但是在该方法的第一次迭代之后,我的数组返回null,即使函数运行正常。如果您能帮我找出问题所在,我们将不胜感激 var processPage = function() { //Gather links var links = this.evaluate(function() { //links is the arr

我正在尝试使用CasperJS编写一个spider,用于解析页面和提取相关链接。该网站以文件和文件夹的分层视图为特色。我已经编写了一个递归方法来执行文件结构的导航,但是在该方法的第一次迭代之后,我的数组返回null,即使函数运行正常。如果您能帮我找出问题所在,我们将不胜感激

var processPage = function() {

    //Gather links
    var links = this.evaluate(function() { //links is the array being set to null
        var elements = document.querySelectorAll("a");
        return Array.prototype.map.call(elements, function(e) {
            //check link matches our white list
            var matchesWhitelist = false;

            var fileDescription = e.querySelector("span").innerHTML;
            console.log("span text:" + fileDescription);

            //begin checking
            if (fileDescription.indexOf('.mp3') != -1) matchesWhitelist = true;
            //if (fileDescription.indexOf('.wmv') != -1) .... etc

            //failing that is the link for a folder rather than a file
            var hrefLink = e.getAttribute("href");
            if (hrefLink.indexOf('folder-files') != -1) matchesWhitelist = true;

            if (matchesWhitelist) {
                console.log('match');
                console.log('Adding link: ' + hrefLink)
                return hrefLink;
            }
            else {
                console.log('no match');
            }
        });
    });

console.log("linkslength: " + links.length); // links will be null upon recursion

for (var i = 0; i < links.length; i++) {

        //check link matches our 'whitelist'
        this.thenOpen("https://TLD" + links[i]).then(function() {
            this.echo("New URL: " + this.getCurrentUrl());

            //check for files
            if (this.exists(".fileDownload")) {
                //extract link
            } else {
                //assume that this is a 'folder' link and send to be processed for more links
                casper.then(processPage); //continue recursion
            };
        });
    }
var processPage=function(){
//收集链接
var links=this.evaluate(function(){//links是设置为null的数组
var元素=document.querySelectorAll(“a”);
返回Array.prototype.map.call(元素,函数(e){
//检查链接是否与我们的白名单匹配
var matcheswitelist=false;
var fileDescription=e.querySelector(“span”).innerHTML;
console.log(“span text:+fileDescription”);
//开始检查
如果(fileDescription.indexOf('.mp3')!=1)匹配白名单=true;
//if(fileDescription.indexOf('.wmv')!=-1)…等
//失败的是文件夹而不是文件的链接
var hrefLink=e.getAttribute(“href”);
如果(hrefLink.indexOf('folder-files')!=1)匹配白名单=true;
如果(匹配白名单){
console.log('match');
log('添加链接:'+hrefLink)
返回赫雷弗林克;
}
否则{
console.log(“不匹配”);
}
});
});
console.log(“linkslength:+links.length);//递归时链接将为null
对于(变量i=0;i

谢谢

如果
匹配白名单
为false,则映射函数不会返回任何内容,因此
链接
数组中的某些项是未定义的


其他问题:并非页面上的所有链接都需要包含跨距。访问
innerHTML
会破坏您的功能。并且:我看不到已经爬网的页面数组。任何循环链接都会导致爬网程序陷入无休止的循环。

您似乎想要一个缩减的集合

这意味着您应该使用
.filter
而不是
.map
,如果要保留链接,则返回truthy值,否则返回false值

return Array.prototype.filter.call(elements, function(e) {

     //...

    if (matchesWhitelist) {
        console.log('match');
        console.log('Adding link: ' + hrefLink)
        return true;
    }
    else {
        console.log('no match');
    }
});
如果不需要日志记录,只需返回
matcheswitelist

return Array.prototype.filter.call(elements, function(e) {

     //...

    return matchesWhitelist;
});
所以,摆脱日志记录,您可以将过滤器减少到这个程度

return Array.prototype.filter.call(elements, function(e) {

    return e.getAttribute("href").indexOf('folder-files') != -1 ||
           e.querySelector("span").innerHTML.indexOf('.mp3') != -1;
});

我希望我能接受你的两个答案,因为它们都有助于我找到问题的根源。我已经把事情复杂化了,通过应用过滤器首先将集合减少到我需要的元素,然后执行映射,这样我就可以返回一个只包含所需链接的数组来解决问题。代码使用的是

var processPage = function() {
    var url;
    //Gather links
    var links = this.evaluate(function() {
        var elements = document.querySelectorAll("a");
        var filteredElementsList = Array.prototype.filter.call(elements, function(e) {

            //check link matches our white list

            var matchesWhitelist = false;

            var fileDescription = e.querySelector("span").innerHTML;
            console.log("span text:" + fileDescription);

            //begin checking
            if (fileDescription.indexOf('.mp3') != -1) matchesWhitelist = true;

            //failing that is the link for a folder rather than a file
            var hrefLink = e.getAttribute("href");
            if (hrefLink.indexOf('folder-files') != -1) matchesWhitelist = true;

            if (matchesWhitelist) {
                console.log('match');
                console.log('Adding link: ' + hrefLink)
            } else {
                console.log('no match');
            }

            return matchesWhitelist;
        });

        return Array.prototype.map.call(filteredElementsList, function(e) {
            return e.getAttribute("href");
        });
    });

该脚本现在可以工作并提取我需要的每个链接。再次感谢您的帮助。

您所说的“
链接
将为
null
”是什么意思?Array.map始终在第一次迭代控制台上返回一个数组。log(“linkslength:+links.length”)将返回(如预期的那样)“linkslength:8”这是正确的。在第二次迭代中,同一行输出:TypeError:“undefined”不是对象(计算“links.length”)如果我只是将链接传递给console.log,那么它也会输出null。在第二次迭代期间,Array.map内联函数运行正常,因为我正在获得“匹配”和“添加链接”控制台输出。这非常奇怪,就像内联函数一旦退出,链接突然超出范围。这是什么意思。评估你的函数on?this.evaluate由CasperJS用于计算远程页面上下文中的表达式。我对细节有点模糊,但据我所知,如果没有它,我将无法访问远程页面DOM。这里有一个更好的解释:但是,这不会将元素映射到URL-您需要两者