这是我正在运行的脚本:
//Require CasperJS
var casper = require('casper').create();
//Scraping Courserank
var base = "https://www.courserank.com";
var home = base + "/w/home";
var schools = base + "/w/schools?switchSchool=1";
//First, navigate to homepage and login
casper.start(home, function() {
console.log('Logging in...');
//Fill in the login form
this.fill(
'form[action="login"]',
{ username : 'hatboysam@gmail.com', password : "****" },
true
);
});
function getSchools() {
var arr = document.querySelectorAll('div.link');
return arr;
}
//Go to the schools page
casper.then(function() {
console.log(this.getCurrentUrl());
//Open the school choice page
casper.open(schools).then(function() {
console.log(this.getCurrentUrl());
//Get all school links
var schools_arr = this.evaluate(getSchools);
console.log(schools_arr.length);
Array.prototype.map.call(schools_arr, function(elem) {
console.log(elem.innerHTML);
});
});
});
casper.run();
一切顺利,直到地图调用的内部循环,特别是console.log(elem.innerHTML)
。 schools_arr
中的许多元素都是null。如果我在if(elem != null) { ... }
语句周围添加一个console.log
,那一切都很好,但是这就失败了。当我在页面上的Chrome控制台中运行相同的document.querySelectorAll
时,NodeList中的513个元素都不为空。 CasperJS还报告了513个元素,但它显示许多元素为null。这里发生了什么?页面是否未完全加载?我之前从未使用过CasperJS,如果这是一个新手的错误,那就很抱歉。
答案 0 :(得分:5)
您无法使用evaluate()
从页面上下文返回本机节点元素;您必须Array#map
使用JSON.parse
反序列化的内容。
因此,您的getSchools()
函数应该执行以下操作:
function getSchools() {
var arr = document.querySelectorAll('div.link');
return Array.prototype.map.call(arr, function(elem) {
return elem.innerHTML;
});
}
虽然我不知道你可以用节点innerHTML字符串内容做什么...所以通常最好将元素映射到你需要的确切属性:
function getSchools() {
var arr = document.querySelectorAll('div.link a');
return Array.prototype.map.call(arr, function(elem) {
return elem.getAttribute('href');
});
}
根据评论中的要求修改,以获取所有链接的内部文字:
function getSchools() {
var arr = document.querySelectorAll('div.link a');
return Array.prototype.map.call(arr, function(elem) {
return elem.textContent;
});
}