querySelectorAll not recognizing var

瘦欲@ 提交于 2019-12-30 13:58:22

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!