如何使用PhantomJS浏览分页网站

How to navigate a paginated website with PhantomJS?

本文关键字:分页 网站 浏览 PhantomJS 何使用      更新时间:2023-12-22

我需要浏览一个已分页的网站,分页会引发一个Ajax请求,该请求将向页面带来新数据。

现在我有一个工作示例代码,它将等待20秒,然后单击链接("ul.pageNavi-li.next")

url = 'https://www.somewebsite.com';
// open the url
var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 5.2; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0';
page.open(url, function (status) {

    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        window.setTimeout(function () { // Wait 20 seconds so the page loads
            page.render('1.png');
            // Begin - click on the pagination 
            page.evaluate( function() {
                // find element to send click to
                var element = document.querySelector( 'ul.pageNavi li.next' );
                // create a mouse click event
                var event = document.createEvent( 'MouseEvents' );
                event.initMouseEvent( 'click', true, true, window, 1, 0, 0 );
                // send click to element
                element.dispatchEvent( event );                     
            });         
            // End - click on the pagination        
            page.render('2.png');
            phantom.exit();
        }, 20000); // Change timeout as required to allow sufficient time 
    }
});

上面的代码正在工作,我成功地转到了第2页。现在我陷入了实现循环的困境,所以我可以导航到以下页面。

每次点击之间我需要等待几秒钟,我已经实现了这段代码,但这不起作用。

url = 'https://www.somewebsite.com';
// open the url
var page = require('webpage').create();
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 5.2; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0';
page.open(url, function (status) {

    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        window.setTimeout(function () { // Wait 20 seconds so the page loads
            var morelinks = moreLinks();
            var i = 0;
            page.render(i + '.png');
            console.log('1: ' + morelinks); 
            while (morelinks != 0) {
                window.setTimeout(function () { // Wait 20 seconds so the page loads
                    i++;
                    // Begin
                    page.evaluate( function() {
                        // find element to send click to
                        var element = document.querySelector( 'ul.pageNavi li.next' );
                        // create a mouse click event
                        var event = document.createEvent( 'MouseEvents' );
                        event.initMouseEvent( 'click', true, true, window, 1, 0, 0 );
                        // send click to element
                        element.dispatchEvent( event );                     
                    });         
                    // End
                    page.render(i + '.png');
                    morelinks = moreLinks();
                    console.log('2: ' + morelinks);
                }, 20000); // Change timeout as required to allow sufficient time  
            }           
            phantom.exit();
        }, 20000); // Change timeout as required to allow sufficient time 
    }
});
function moreLinks() {
    var morelinks = page.evaluate(function() {
        return $('ul.pageNavi li.next').length;
    });
    return morelinks;
}
function getHref() {
    var links = page.evaluate(function() {
        return $('#ulSearchResults li a');
    }); 
    return links;
}

有人能给我一个关于如何实现导航到以下页面的线索吗?

您有两个问题。

提前退出

您正在处理异步函数(在循环中)。循环结束后,您立即退出(phantom.exit())。此时,甚至没有一个异步函数开始执行。

异步函数的循环

您应该问问自己,如果异步函数是从循环中调用的,那么如何评估它们。循环结束后,还没有执行任何函数。在第一个超时触发之后,所有其他超时也会触发,因为setTimeout基本上是同时调用的。

有很多方法可以解决这个问题。这里有两个:

1.静态超时延迟

以一种从上一个函数延迟调用超时的方式来安排超时。

while (morelinks != 0) {
    // IIFE to keep a proper reference to `i`
    (function(i){
        setTimeout(function () {
            // do your stuff
        }, 20000 * i);
    })(i);
    i++;
}

2.递归(推荐

伪代码和实代码的混合。

function scrapePage(){
    page.render(i + '.png');
    if (exists(".next")) {
        click(".next");
        setTimeout(function (){
            scrapePage();
        }, 5000);
    } else {
        phantom.exit();
    }
}
page.open(url, function(){
    scrapePage();
});

关键是检查下一个按钮是否存在(或可见或已启用),然后单击它。如果不存在,则表明您已进入最后一页,可以安全退出。

我相信您可以自己实现exists()click()函数。

使用waitFor

不要在第二个建议中等待静态时间,而是使用示例中的waitFor函数,通过查找最后加载的合适选择器来等待页面完全加载。