问题
I am using casperjs for some webscraping and am having a strange problem. I want to be able to construct a CSS path from strings and get an array using 'querySelectorAll' like below:
var tier = '-ou-';
var index = 'div.list > div > a[href*="' + tier + '"]';
var battles = document.querySelectorAll(index);
However, this does not work, and battles returns null.
This version works:
var links = document.querySelectorAll('div.list > div > a[href*="-ou-"]');
But none other does. I also tried:
var index = 'div.list > div > a[href*="-ou-"]';
var battles = document.querySelectorAll(String(index));
and
var index = 'div.list > div > a[href*="-ou-"]';
var battles = document.querySelector(index);
and all combinations of the above, just as a sanity check, and none worked. I am relatively new to javascript so I feel I may be missing something obvious, but I have no idea what.
EDIT: My entire program is below. As is, it works fine. If the commented line in getBattles is used instead of the one below it, it no longer works (var 'battles' becomes null)
var casper = require('casper').create();
var url = 'http://play.pokemonshowdown.com/';
var battles = [];
var tier = '-ou-';
var index = "div.list > div > a[href*=\"" + tier + "\"]";
function getBattles() {
//var battles = document.querySelectorAll(index);
var battles = document.querySelectorAll('div.list > div > a[href*="-ou-"]');
return Array.prototype.map.call(battles, function(e) {
return e.getAttribute('href');
});
}
casper
.start(url)
.then(function() {
if(this.exists('div.leftmenu')) {
this.echo('something works');
}
else {
this.echo('nothing works');
}
})
.thenClick('button[name="roomlist"]')
.then(function(){
this.echo("This one is done.");
})
.waitForSelector('div.list > div > a', function(){
battles = this.evaluate(getBattles);
this.echo(this.getHTML('div.list > div:nth-child(2) > a'));
})
.then(function(){
this.echo("This two is done.");
});
casper.run(function() {
this.echo(battles.length + ' battles found:');
this.echo(' - ' + battles.join('\n - ')).exit();
});
回答1:
CasperJS and PhantomJS have two contexts. The inner context which is programmed through casper.evaluate() is sandboxed. It means that it has no access to variables defined outside. You need to explicitly pass those variables in:
var index = 'div.list > div > a[href*="' + tier + '"]';
function getBattles(innerIndex) {
var battles = document.querySelectorAll(innerIndex);
return Array.prototype.map.call(battles, function(e) {
return e.getAttribute('href');
});
}
...
battles = casper.evaluate(getBattles, index);
The PhantomJS documentation of evaluate() has an important note:
Note: The arguments and the return value to the
evaluate
function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.Closures, functions, DOM nodes, etc. will not work!
来源:https://stackoverflow.com/questions/29721176/queryselectorall-not-recognizing-var