Casperjs ajax调用 - waitForResource和解析错误

Mar*_*ing 1 javascript ajax casperjs

Casperjs是一个很棒的工具.我已经能够理解某些基础知识.但是,我正在努力解决两个问题.首先,为了关闭原因,我将代码分成几个函数.我得到一个解析错误.我已经添加了选项verbose: true, logLevel: "debug",看它是否指出了行号,但我没有得到任何结果.其次,我想做一个异步的ajax调用.我正在使用,waitFor但我读了这篇文章是为了更有效的方式.如何设置waitForResource()跟踪AJAX请求?以及如何显示解析错误行?

var urls = ['http://9gag.tv/'];
var casper = require('casper').create({
    verbose: true,
    logLevel: "debug"
});

function getNumberOfItems(casper) {
    return casper.getElementsInfo(".listview .badge-grid-item").length;
}

function tryAndScroll(casper) {
  casper.page.scrollPosition = { top: casper.page.scrollPosition["top"] + 4000, left: 0 };
  var info = casper.getElementInfo('.badge-post-grid-load-more');
  if (info.visible) {
    var curItems = getNumberOfItems(casper);
    if( curItems <= 60 ) {
        casper.waitFor(function check(){
          return curItems != getNumberOfItems(casper);
        }, function then(){
          tryAndScroll(this);
        }, function onTimeout(){
          this.echo("Timout reached");
        }, 10000);
    }
  } else {
    casper.echo("no more items");
  }

}

function combineArrays(x, y) {
    var result = [];
    for(var i = 0, i < page_links.length; i++) {
        result[i] = {};
        result[i].page_link = x[i];
        result[i].video_link = y[i];
    }
    return result;
}

function linkScraper(x){
    var page_links = [];
    var youtube = [];
    for (var i = 0; i < x.length; i++)
    { // start for loop
        casper.thenOpen(x[i], function() {
            //Scroll down for elements
            tryAndScroll(this);
            casper.then(function() {
              this.getElementsInfo('.title').forEach(function(element) {
                // skip elements that don't have a href attribute...
                if (!element.attributes.href) {
                  return;
                }
                page_links.push( element["attributes"]["href"] );
                casper.thenOpen(element.attributes.href, function() {
                  this.click('.responsivewrapper');
                }).then(function(){
                  casper.each(this.getElementsInfo('.badge-youtube-player'), function(casper, element, j) {
                    youtube.push( element["attributes"]["src"] );
                  });
                })localhost;
              });
            });
        });
    }
    return combineArrays(page_links,youtube);
}

function stringifyResult(webpages){
    //Pass link array to linkScraper
    var linksArr = linkScraper.call(this, webpages);
    //send results to php page
     server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
     this.waitFor( function() {
         response = this.evaluate(function() {
            $.ajax({
                type: "POST",
                url: server,
                data: JSON.stringify(linksArr),
                //dataType: 'json',
                contentType: "application/json",
                success: function (data) {
                    this.echo("All done.");
                    return this.exit();
                    //return data.responseText;
                },
                error: function (xhr,status,error){
                    return this.echo(error);
                }
            });
         });
     });
}



casper.start().then(function() {
    this.echo("Starting");
});
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
casper.run(stringifyResult.call(this, urls));
Run Code Online (Sandbox Code Playgroud)

Art*_* B. 7

您的代码存在许多问题.

1.语法错误

CasperJS和PhantomJS本身不会向您显示语法错误的位置,但它可能符合要求for(var i = 0, i < page_links.length; i++) {.更改,;.并page_links没有在这一行中定义.你可能意味着x.
对于未来:CasperJS脚本是纯JavaScript.您可以使用jslint.com等在线工具来查找此类错误(以及代码的其他问题).

还有一个错位localhost.

2. this

this 根据它的放置位置有很多含义.

a)全球 this

以最后一行为例:

casper.run(stringifyResult.call(this, urls));
Run Code Online (Sandbox Code Playgroud)

this超出了所有功能.所以它引用window(是的,有两个单独的window对象,一个在页面上下文中,一个在外部).它没有提到casper你可能期望的那个.使用:

casper.run(stringifyResult.call(casper, urls));
Run Code Online (Sandbox Code Playgroud)

(^非最终代码:见6.)

b)jQuery回调

this里面:

success: function (data) {
    this.echo("All done.");
    return this.exit();
},
Run Code Online (Sandbox Code Playgroud)

指的jqXHR是jQuery 的对象(顺便说一句,你也不能从函数内的异步函数返回一些东西).它与CasperJS无关.此外,不可能从页面上下文(内部casper.evaluate())调用CasperJS函数,因为页面上下文是沙箱.它无法访问外部定义的变量(包括linksArrserver).有关更多信息,请参阅

3.不必要 waitFor

waitFor永远不会完成,但你可能是这样设计的,这样就可以发送你的AJAX请求了.问题是每隔20毫秒就会发送相同的破坏请求.

4.发送AJAX请求

CasperJS提供了一个在页面上下文中发送AJAX请求的实用程序:__utils__.sendAJAX().它还默认阻止执行,因此不需要以越界的方式等待请求.

function stringifyResult(webpages){
    var linksArr = linkScraper.call(this, webpages);

    //send results to php page
    server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
    this.evaluate(function(server, linksArr){
        __utils__.sendAJAX(server, "POST", JSON.stringify(linksArr));
    }, server, linksArr);
}
Run Code Online (Sandbox Code Playgroud)

(^非最终代码:见5.)

5.从异步函数返回

All then*wait*CasperJS函数是异步的.通过调用它们,您可以安排在当前步骤结束时执行相关步骤.

这意味着你不能返回一些东西linkScraper,因为它包含异步代码.或者至少你不能返回最终结果,因为它们由异步代码填充.但是,您可以返回最终将包含结果的数组.

一个可能的解决方法是将组合调用移到linkScraper:

function linkScraper(x){
    var page_links = [];
    var youtube = [];
    // here are asynchronous calls
    return {pl: page_links, yt: youtube};
}
function stringifyResult(webpages){
    var linksObj = linkScraper.call(this, webpages);
    // here linksObj contains empty lists
    this.then(function(){
        // here linksObj contains populated lists
        var linksArr = combineArrays(linksObj.pl, linksObj.yt);

        server = "http://localhost:8181/hashtag_pull/lib/9GagPrivateApi.php";
        this.evaluate(function(server, linksArr){
            __utils__.sendAJAX(server, "POST", JSON.stringify(linksArr));
        }, server, linksArr); 
    });
}
Run Code Online (Sandbox Code Playgroud)

6. exit

casper.exit()是立即的.所以当你调用它时,执行就会停止.在调用它时必须要小心,因为可能存在仍然安排步骤的情况.

有一种方法可以casper.exit()通过不提供回调来避免调用casper.run().如果您提供此类回调,则在执行所有步骤时将不会自动退出.

casper.then(stringifyResult.call(casper, urls)).run();
Run Code Online (Sandbox Code Playgroud)