在Casper重复功能之外无法访问数组

Array is not accessible outside of Casper repeat function

本文关键字:访问 数组 Casper 功能      更新时间:2023-09-26

我的目标是获取工作现场的每个工作链接,通过以下工作链接转到每个工作详细信息页面,通过CASPERJS下载并保存在html中的详细信息。由于每次我们在作业链接和作业详细信息页面之间来回切换时,每个作业链接的 id 都会发生变化,因此每次都需要在 casper.repeat 下获取所有作业 ID。但是 NoOfLink 数组在重复函数之外变为空 [我在代码中注释该部分]。问题出在哪里?

var casper = require('casper').create();
var noOfRecordsToLoop = 0;
var TotalNoofNullElement = 0;
var NoOfLink = [];
var x = require('casper').selectXPath;
casper.echo(''nStart loding site......');
//---------------------------------------------Load and Scroll the site---------------------------------------//
casper.start('https://........../...../.......Careers/');
casper.wait(10000, function () {
    //---------Total no of Job posting------//
    var noOfRecords = this.fetchText(x('//*[@id="...........................jobProfile......"]'));
    noOfRecordsToLoop = noOfRecords.replace(/[^0-9]/g, "");
    var totalNoOfPage = Math.ceil(parseInt(noOfRecords) / 50);
    casper.echo(''nStart scrolling site......');
    casper.repeat(totalNoOfPage, function () {
        this.scrollToBottom(); //-----------------------Scroll down
        casper.wait(10000, function () {})
    })
})
//------------------------------------------------Load and Scroll the site---------------------------------------//

casper.then(function () {
    //-----------------------------------------Get all the link elements  --------------------------//
    var countForLink = 0;
    var numTimesForRpt = noOfRecordsToLoop;
    var numTimes = noOfRecordsToLoop;
    casper.repeat(numTimesForRpt, function () {
        RetElement = this.evaluate(function () {
            var startingRow = '//*[contains(@id, "...-uid-")]'
                var element = __utils__.getElementByXPath(startingRow).getAttribute('id');
            return element;
        });
        var count = RetElement.replace(/[^0-9]/g, "");
        casper.repeat(numTimes, function () {
            var MatchElements = this.evaluate(function (count) {
                    var xp = '//*[contains(@id, "...-uid-' + count + '")]'
                        var element = __utils__.getElementByXPath(xp).getAttribute('id');
                    return element;
                }, count++);
            if (!MatchElements) {
                TotalNoofNullElement = TotalNoofNullElement + 1
            } else {
                NoOfLink.push(MatchElements);
            }
            //**Here array elements are accessible**
            for (var k = 0; k < NoOfLink.length; k++) {
                this.echo(NoOfLink[k]);
            }
        });
        //**But here array elements are not accessible outside of repeat** function
        this.echo("Size of array is" + NoOfLink.length);
        for (var q = 0; q < NoOfLink.length; q++) {
            this.echo(NoOfLink[q]);
        }
        //-----------------------------------------Get all the link elements----------------------------//
        //------------------------------------Go to the Job Detail Page Extract HTML and Save---------------------------//
        this.echo("'n Inside repeat to Generate HTML");
        var num = NoOfLink[countForLink];
        this.echo("'nLink id is " + NoOfLink[countForLink]);
        num = parseInt(num.replace(/[^0-9]/g, ""));
        this.echo("'nNum is " + num);
        //-----------------Click to go to the Job Detail Page------------------//
        casper.thenClick(x('//*[@id="..-uid-' + num + '"]/div/div'));
        casper.wait(5000, function getJobDetail() {
            var content = this.getElementInfo(x(".//*[contains(@id,'......t-uid-')]")).html;
            var divStart = '<div id="extrdHtml">'
                var divEnd = '</div>'
                var body = divStart + content + divEnd
                this.echo("'nContent of Job detail :" + body);
            var fs = require('fs');
            fs.write('extractedJob' + NoOfLink[countForLink] + '.html', body, 'w');
            this.echo("'nFile saved");
            //------------------------------------Go to the Job Detail Page Extract HTML and Save---------------------------//
        }); //casper.wait
        casper.back();
        casper.wait(5000);
        countForLink++
    }); //casper.repeat
}); //casper.then
//-------------------------------------------Get all the link elements------------------------------//
casper.run();

有两个重复循环。

  1. casper.repeat(numTimesForRpt, function () { - 这是主外环,第二回路所在的位置。
  2. casper.repeat(numTimes, function () – 我在哪里获取链接并填充NoOfLink数组。我正在尝试在第二个循环(在主外循环内)之外获取数组元素值,但它不起作用。

所有then*wait*函数都是异步步进函数。如果调用它们,则计划在当前步骤结束时执行的步骤。 casper.repeat() 是一个使用casper.then()的函数,因此也是异步的。casper.repeat()之后的每个同步代码都将在repeat回调的内容之前执行。

您有两种选择:

  1. casper.repeat()后的所有内容包装在casper.then()中,以使其异步或
  2. 使用正常的同步循环而不是repeat,如果不需要像您的情况那样异步计算repeat的回调。

顺便说一下,您通常可以通过利用 CasperJS 提供的帮助程序函数来减少代码。例如,您不需要仅使用 evaluate() 来获取 XPath 某些元素的 id 属性。你可以做到这一点 casper.getElementsAttribute() .

例:

var count = RetElement.replace(/[^0-9]/g, "");
for(var i = count; i < (numTimes + count); i++) {
    var MatchElements = this.getElementsAttribute(x('//*[contains(@id, "...-uid-' + i + '")]'), 'id');
    if (!MatchElements) {
        TotalNoofNullElement = TotalNoofNullElement + 1
    } else {
        NoOfLink.push(MatchElements);
    }
    //**Here array elements are accessible**
    for (var k = 0; k < NoOfLink.length; k++) {
        this.echo(NoOfLink[k]);
    }
}