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

mrd*_*th4 2 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();
Run Code Online (Sandbox Code Playgroud)

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

Art*_* B. 13

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

出口

正如您所正确指出的那样,您遇到了问题phantom.exit().由于page.open()setTimeout()异步,您只需在完成后退出.当您phantom.exit()在脚本结束时调用时,您将在第一页加载之前退出.

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

页面上下文

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

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

然后,当您只想写一次时,您不需要打开流.更改:

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

fs.write('new_test.txt', html + '\n', 'a');
Run Code Online (Sandbox Code Playgroud)

递归步骤

调用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();
Run Code Online (Sandbox Code Playgroud)