【问题标题】:Casperjs ajax calls - waitForResource and parse errorsCasperjs ajax 调用 - waitForResource 和解析错误
【发布时间】:2015-03-18 23:01:53
【问题描述】:

Casperjs 是一个很棒的工具。我已经能够理解某些基础知识。但是,我正在尝试解决两个问题。首先,出于关闭的原因,我将代码拆分为几个函数。我收到一个解析错误。我已将选项添加到 verbose: true, logLevel: "debug" 并查看它是否指出了行号,但我没有得到任何结果。其次,我想进行一个异步的 ajax 调用。我正在使用waitFor,但我阅读了THIS 文章以获得更有效的方法。如何设置 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));

【问题讨论】:

    标签: javascript ajax casperjs


    【解决方案1】:

    你的代码有很多问题。

    1。语法错误

    CasperJS 和 PhantomJS 本身不会显示语法错误的位置,但它可能在 for(var i = 0, i &lt; page_links.length; i++) { 行中。将, 更改为;。并且page_links 未在此行中定义。你的意思可能是x
    未来:CasperJS 脚本是纯 JavaScript。您可以使用jslint.com 等在线工具来查找此类错误(以及您的代码的其他问题)。

    还有一个错位的localhost

    2。 this

    this 有很多含义,具体取决于它的放置位置。

    a) 全球this

    以最后一行为例:

    casper.run(stringifyResult.call(this, urls));
    

    这个this 在所有函数之外。所以它指的是window(是的,有两个单独的window 对象,一个在页面上下文内部,一个在页面上下文外部)。它没有引用您可能预期的casper。使用:

    casper.run(stringifyResult.call(casper, urls));
    

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

    b) jQuery 回调

    this 内部:

    success: function (data) {
        this.echo("All done.");
        return this.exit();
    },
    

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

    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);
    }
    

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

    5。从异步函数返回

    所有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); 
        });
    }
    

    6。 exit

    casper.exit() 是即时的。因此,当您调用它时,执行将停止。您必须小心何时调用它,因为可能仍然有计划的步骤。

    有一种方法可以避免调用casper.exit(),即不提供对casper.run() 的回调。如果你提供了这样的回调,那么当所有步骤都执行完时,不会自动退出。

    casper.then(stringifyResult.call(casper, urls)).run();
    

    【讨论】:

    • 感谢您提供详细解释的答案。我会进行更改并记住您对语法错误的建议。
    • 我从“linkScraper”得到一个空的结果集。我试图回显结果,但没有显示。我是否将其错误地分配给变量?我试过打电话给linkScraper.call(this, webpages);linkScraper.call(webpages);
    • 你应该得到一个错误,因为for(var i = 0; i &lt; page_links.length; i++) {中的page_links没有定义。应该是x
    • 我改了。我检查了其他所有内容。但是,它没有为linksArr 显示任何内容。在我的问题下面,我将我的代码编辑为我现有的内容。
    • 是的,还有一个问题。我已经更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 2012-05-14
    • 1970-01-01
    相关资源
    最近更新 更多