CasperJS,在刮擦期间多次点击

时间:2015-02-24 00:12:08

标签: javascript phantomjs casperjs

我正在尝试抓取一个页面,并将所有数据作为JSON返回。这个过程是我首先打开www.domain.com,我将各种信息提取到"节点"数组,但是对于每个节点,还有另一个页面,我想从节点数组中提取附加数据并存储。我需要在循环中执行此操作,或者至少能够通过" x"变量周围所以我知道将数据推送到数组的位置。

我已经删除了这个代码,并且没有检查它是否有效,但主要版本我工作正常

非常感谢任何帮助......谢谢

var nodes = {};

var casper = require('casper').create({

    pageSettings: {
        loadImages:  false,           
    },             
    verbose: true                   
});


var url = "http://www.domain.com";


function get_rows() 
{
  var nodes = {};

  var el = document.querySelectorAll(".rows");

  nodes["rows"] = {};

  for(var x = 0; x < el.length; ++x) 
  {
    // Set the arrays
    nodes["rows"][x] = {};


    nodes["rows"][x] = el[x].innerHTML;


    // THIS DATA IS ON A SEPARATE PAGE
    // el[x].click IS HOW YOU'D VISIT THAT PAGE
    nodes["rows"][x]["data"] = {};

  }

  return nodes;
}


function get_data()
{
  casper.echo("get_data");

  rows = casper.evaluate(get_rows);

  casper.echo(JSON.stringify(rows));

}

casper.start(url, function() 
{
  this.echo('Starting...' + this.getTitle());
});

casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0');
casper.viewport(320, 480);

casper.waitFor
(
  function check() 
  {
    return this.evaluate(function() 
    {
      return $('.content').is(':visible');
    });
  }, 
  function then() 
  {    
    this.capture("/work/screen.png");

    // Lets go get the data
    this.echo("About to get_data()");
    get_data();
  }, 
  function timeout() 
  { 
    // step to execute if check has failed
    this.echo("Timeout: page did not load in time...").exit();
  }
);


casper.run();

2 个答案:

答案 0 :(得分:0)

您必须将get_rows功能拆分为多个功能。第一个将检索.rows个元素的数量。 casper.getElementsInfo()为每个匹配元素提供html属性,并且可以在页面上下文之外调用。

var nodes;
var x = require('casper').selectXPath;
casper.then(function(){
    nodes = {
        rows: {}
    };
    var elements = this.getElementsInfo(".rows");
    for(var i = 0; i < elements.length; i++) {
        nodes.rows[i] = {
            html: elements[i].html
        };
        (function(i){
            // TODO: click on the correct link
            casper.thenClick(x("(//*[contains(@class,'rows')])["+(i+1)+"]//a"));
            casper.then(function(){
                nodes.rows[i].data = this.evaluate(function(){
                    return { stuff: "whatever" }; // scrape here
                });
            });
            casper.back(); // assumes this works for your page
        })(i);
    }
}).then(function(){
    this.echo(JSON.stringify(nodes.rows, undefined, 4));
});

IIFE((function(i){...})(i);)很重要,否则只会填充最后一个i。这是因为JavaScript具有功能级别范围和CasperJS&#39; then*函数是异步的。

如果casper.back()不适合您,则需要使用casper.thenOpen()重新加载主页。

答案 1 :(得分:0)

这是我到目前为止的地方......第一个评估返回一个对象并完美地工作,但在每个“夹具”中我想要获取另一个数据页面,要点击的元素只是一个重复的类称为“.Fixture”,所以我使用nth-child()来尝试定位相关元素。代码实际上永远不会创建捕获

    fixtures = casper.evaluate(get_fixtures);

  casper.echo("Fixtures: "+Object.keys(fixtures).length );

  casper.then(function()
  {    
    Object.keys(fixtures).forEach(function(key) 
    {
      casper.echo(fixtures[key]["competition"]);

      (function(key)
      {
        casper.echo(".Fixture:nth-child("+key+")");

        var pageturnString = key.toString();
        var linknum = 'div.Fixture:nth-child('+pageturnString+')';

        casper.thenClick(linknum);

        casper.then(function()
        {
          casper.capture('/work/screen_click.png');
        });
        casper.back(); // assumes this works for your page
      })(key);

    });

  }).then(function()
  {
      casper.echo("END");
  });