PhantomJS在对象类更改后不呈现额外信息

时间:2013-11-13 21:35:00

标签: javascript phantomjs

我正在尝试获取仅在单击侧面菜单项时显示的列表信息。侧面菜单项是一个列表项,当显示我需要的信息时,其类会改变。列表项是:

<li class="treeItem" dataid="1" parentid="0" sportid="HOR"><div class="treeItemText">Horse Racing<div>

当用户点击包含此列表项的左侧面板中的“赛马”时,将“打开”类添加到该列表项,然后列表项展开生成表所需的显示代码

<li class="treeItem open" dataid="1" parentid="0" sportid="HOR" loaded="true"><div class="treeItemText">Horse Racing<div></div></div><div class="loader" style="display: none; "></div><ul class="level1" style="display: block; "><li class="treeItem" dataid="65365" parentid="1" sportid="HOR"><div class="treeItemText">Dundalk<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="79261" parentid="1" sportid="HOR"><div class="treeItemText">Exeter<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="71557" parentid="1" sportid="HOR"><div class="treeItemText">Fairview<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="65428" parentid="1" sportid="HOR"><div class="treeItemText">Happy Valley<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="65433" parentid="1" sportid="HOR"><div class="treeItemText">Kempton<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="71544" parentid="1" sportid="HOR"><div class="treeItemText">Kenilworth<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="68710" parentid="1" sportid="HOR"><div class="treeItemText">Lingfield<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="69378" parentid="1" sportid="HOR"><div class="treeItemText">Summer Cup - Antepost<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="65459" parentid="1" sportid="HOR"><div class="treeItemText">Turffontein Standside<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li><li class="treeItem" dataid="65463" parentid="1" sportid="HOR"><div class="treeItemText">Vaal Sand<div></div></div><div class="loader"></div><div class="checkbox">&nbsp;</div></li></ul></li>

我已成功(9小时,在找到基于属性的元素后遇到addClass问题)设法使用以下javascript将“open”添加到列表项类

var page = require('webpage').create();
page.open('http://www.bettingworld.co.za/', function (s) {

window.setTimeout(function () { 
    var sports = page.evaluate(function(){
        $( "li:eq(48)" ).addClass( "open" );

        console.log("YYYYYY");
     });

    page.render('page.png');
    console.log(page.content);
    phantom.exit();
}, 60000);

});

并在命令行jason:>./phantomjs javaRender.js > new.html运行phantomjs(我的网络连接通过我的手机,所以我将超时设置为一分钟。)。 虽然类已更改,但列表项未打开,我无法在输出中看到所需的数据(new.html)。我对JavaScript没有很好的经验,但是假设单击菜单中的项目会导致页面上的一些javascript执行。 我浏览了页面上的javascripts,但是有很多,变量名是单个字符(arg!)。 我希望虽然没有渲染额外数据的原因是因为我在渲染页面方面做了一些明显错误的事情。会是这种情况,还是我需要找到点击列表项时执行的javascript?我看不到对javascript“ on clicked ”的调用,这是我所期望的。

1 个答案:

答案 0 :(得分:1)

onClick确实,“open”类被添加到该li元素中。但那不是唯一的事情!另外,进行异步网络请求(AJAX),请求子菜单的html / data;它们在装载时会显示一个小旋转器GIF。

因此,要在PhantomJS中模拟此行为,您必须实际重新创建该点击。哪个离你的东西不太远!首先,不要将open类添加到<li/>元素,而是执行此操作:

 $( "li:eq(48)" ).click();

这将启动AJAX请求以获取子菜单内容。从那里,你需要“等待”加载子菜单元素。有一个名为waitfor.js的PhantomJS实用程序就是这样做的:你告诉它要等到满足某些条件(在这种情况下,加载子菜单)然后你就可以完成你的功能了。

所以在你的例子中,它可能看起来像这样:

function waitFor(testFx, onReady, timeOutMillis) {
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
        start = new Date().getTime(),
        condition = false,
        interval = setInterval(function() {
            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
                // If not time-out yet and condition not yet fulfilled
                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
            } else {
                if(!condition) {
                    // If condition still not fulfilled (timeout but condition is 'false')
                    console.log("'waitFor()' timeout");
                    phantom.exit(1);
                } else {
                    // Condition fulfilled (timeout and/or condition is 'true')
                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
                    clearInterval(interval); //< Stop this interval
                }
            }
        }, 250); //< repeat check every 250ms
};

var page = require('webpage').create();
page.open('http://www.bettingworld.co.za/', function (s) {

    window.setTimeout(function () { 
        var sports = page.evaluate(function(){
            $( "li:eq(48)" ).click()
         });
        waitFor(function() {
            // Check in the page if a specific element is now visible
            return page.evaluate(function() {
                return ($( "li:eq(48)" ).find('.level1').length > 0);
            });
        }, function() {
            // once it's visible, you can exit & spit out any html
            page.render('page.png');
            console.log(page.content);
           console.log("submenu open");
           phantom.exit();
        });    
    }, 60000);

});