在一个脚本中使用多个page.open

时间:2015-07-02 14:57:33

标签: javascript phantomjs

我的目标是打开许多页面(延迟很短)并将我的数据保存到文件中。

但我的代码不起作用。

var gamesList = [url1,url2,url3];
//gamesList is getting from a file

var urls = [];
var useragent = [];
useragent.push('Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14');
useragent.push('Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50');

var page = require('webpage').create();
page.settings.userAgent = useragent[Math.floor(Math.random() * useragent.length)];
console.log('Loading a web page');


function handle_page(url){
    page.open(url,function(){
        //...
        var html= page.evaluate(function(){
            // ...do stuff...
            page.injectJs('jquery.min.js');
            return $('body').html();
        });
        //save to file
        var file = fs.open('new_test.txt', "w");
        file.write(html + '\n');
        file.close();    

        console.log(html);

        setTimeout(next_page,1000);
    });
}

function next_page(urls){
    var url=urls.shift();
    if(!urls){
        phantom.exit(0);
    }
    handle_page(url);
}

next_page(urls);
phantom.exit();

我在写phantom.exit();的地方有用吗?如果我最后在page.open()回调中写它,那么第一页就会打开。

2 个答案:

答案 0 :(得分:13)

您使用递归打开多个页面的想法是正确的,但是您遇到了一些问题。

退出

正如您所正确指出的那样,phantom.exit()存在问题。由于page.open()setTimeout()是异步的,因此您只需在完成后退出。当您在脚本末尾调用phantom.exit()时,您将在第一页加载之前退出。

只需删除最后一个phantom.exit(),因为您已经在正确的位置有另一个出口。

页面上下文

page.evaluate()提供对DOM上下文(页面上下文)的访问。问题是它是沙箱。在该回调内部,您无法访问外部定义的变量。您可以显式传递变量,但它们必须是page不是的原始对象。您只需访问page内的page.evaluate()即可。您需要在调用page.evaluate()之前注入jQuery。

文件

您通过不更改文件名来覆盖每次迭代中的文件。您需要更改文件名或使用追加模式'a'而不是'w'

然后,当您只想写一次时,您不需要打开流。变化:

var file = fs.open('new_test.txt', "w");
file.write(html + '\n');
file.close();

fs.write('new_test.txt', html + '\n', 'a');

递归步骤

调用next_page()函数的递归步骤要求您传入URL。由于urls已经是全局变量,并且您在每次迭代中都更改了它,因此您无需传入urls

您也不需要添加setTimeout(),因为page.open()回调内部的所有内容都是同步的。

固定脚本

//...
var urls = [/*....*/];

function handle_page(url){
    page.open(url, function(){
        //...
        page.injectJs('jquery.min.js');
        var html = page.evaluate(function(){
            // ...do stuff...
            return $('body').html();
        });
        //save to file
        fs.write('new_test.txt', html + '\n', 'a');

        console.log(html);

        next_page();
    });
}

function next_page(){
    var url = urls.shift();
    if(!url){
        phantom.exit(0);
    }
    handle_page(url);
}

next_page();

答案 1 :(得分:0)

上面的说明对我很有帮助。因此,thanx很多。说到这一点,在这种情况下,有时即使页面已经加载后js函数也呈现,在这种情况下,setTimeout()方法非常有用。而且,在抓取多个网站时遇到了这样的问题。...我以这种方式使用setTimeout()方法,

`

        function handle_page(url){page.open(url, function() {setTimeout(function() {var html_text=page.evaluate(function(){ 
            var is= document.querySelectorAll("li.bookinDetails_c1_180616")[0].textContent;
            var isbn=is.trim();
            //return s1;
            var w,x,y,z,z1,w1,u,a;
            a= document.querySelectorAll("li.selectableBook");
            if(a.length==5){
                w1=document.querySelectorAll("span.bookPrice")[0].textContent;
                w=w1.trim();
                x1=document.querySelectorAll("span.bookPrice")[1].textContent;
                x=x1.trim();
                y1=document.querySelectorAll("span.bookPrice")[2].textContent;
                y=y1.trim();
                z1=document.querySelectorAll("span.bookPrice")[3].textContent;
                z=z1.trim();
                u=isbn+"=>["+"RENT USED:-"+w+","+"RENT NEW:-"+x+","+"BUY USED:-"+y+","+"BUY NEW:-"+z+"]";
                return u;
            }else{
                y1=document.querySelectorAll("span.bookPrice")[0].textContent;
                y=y1.trim();
                z1=document.querySelectorAll("span.bookPrice")[1].textContent;
                z=z1.trim();
                u=isbn+"=>["+"BUY USED:-"+y+","+"BUY NEW:-"+z+"]";
                return u;
            }

        });
        fs.write('html.txt',html_text+'\r\n','a');
        next_page();
    }, 400);

});
}

`