Javascript 在递归方法中将数组设置为null
我正在尝试使用CasperJS编写一个spider,用于解析页面和提取相关链接。该网站以文件和文件夹的分层视图为特色。我已经编写了一个递归方法来执行文件结构的导航,但是在该方法的第一次迭代之后,我的数组返回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
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-您需要两者