Javascript 使用多页。在单个脚本中打开

Javascript 使用多页。在单个脚本中打开,javascript,phantomjs,Javascript,Phantomjs,我的目标是通过以下方式执行PhantomJS: // adding $op and $er for debugging purposes exec('phantomjs script.js', $op, $er); print_r($op); echo $er; 然后在script.js中,我计划使用多个page.open()来捕获不同页面的屏幕截图,例如: var url = 'some dynamic url goes here'; page = require('webpage').cr

我的目标是通过以下方式执行PhantomJS:

// adding $op and $er for debugging purposes
exec('phantomjs script.js', $op, $er);
print_r($op);
echo $er;
然后在
script.js
中,我计划使用多个
page.open()
来捕获不同页面的屏幕截图,例如:

var url = 'some dynamic url goes here';
page = require('webpage').create();
page.open(url, function (status) {
    console.log('opening page 1');  
    page.render('./slide1.png');            
});

page = require('webpage').create();
page.open(url, function (status) {
    console.log('opening page 2');  
    page.render('./slide2.png');        
});

page = require('webpage').create();
page.open(url, function (status) {
    console.log('opening page 3');  
    page.render('./slide3.png');        
    phantom.exit(); //<-- Exiting phantomJS only after opening all 3 pages
});

因此,我只得到了第三页的截图。我不知道为什么PhantomJS跳过第一块和第二块代码(从丢失的
控制台.log()
消息中可以明显看出,应该从第一块和第二块输出),而只执行第三块代码。

问题是第二块
页面.open在第一块完成之前被调用,这可能会导致多个问题。您需要大致如下的逻辑(假设文件名作为命令行参数提供):

对,它是递归的。这样可以确保传递到
page.open的函数的处理在进入下一个文件之前完成,有一点100毫秒的宽限期

顺便说一句,你不需要不断重复

page = require('webpage').create();

我尝试过接受的答案建议,但不起作用(至少对v2.1.1不起作用)

准确地说,被接受的答案在某些时候起作用,但我仍然偶尔遇到失败的page.open()调用,大约90%的时间是在特定的数据集上

我找到的最简单的答案是为每个url实例化一个新的页面模块

// first page
var urlA = "http://first/url"
var pageA = require('webpage').create()

pageA.open(urlA, function(status){
    if (status){
        setTimeout(openPageB, 100) // open second page call
    } else{
        phantom.exit(1)
    }
})

// second page
var urlB = "http://second/url"
var pageB = require('webpage').create()

function openPageB(){
    pageB.open(urlB, function(){
        // ... 
        // ...
    })
}
:

close(){void}

关闭该页并释放与其关联的内存堆。调用此函数后不要使用页面实例

由于某些技术限制,web页面对象可能不会完全被垃圾收集。当重复使用同一对象时,经常会遇到这种情况。调用此函数可能会停止增加堆分配

基本上,在测试close()方法之后,我决定对不同的open()调用使用相同的网页实例太不可靠了,需要说明一下。

可以使用递归:

var page = require('webpage').create();

// the urls to navigate to
var urls = [
    'http://phantomjs.org/',
    'https://twitter.com/sidanmor',
    'https://github.com/sidanmor'
];

var i = 0;

// the recursion function
var genericCallback = function () {
    return function (status) {
        console.log("URL: " + urls[i]);
        console.log("Status: " + status);
        // exit if there was a problem with the navigation
        if (!status || status === 'fail') phantom.exit();

        i++;

        if (status === "success") {

            //-- YOUR STUFF HERE ---------------------- 
            // do your stuff here... I'm taking a picture of the page
            page.render('example' + i + '.png');
            //-----------------------------------------

            if (i < urls.length) {
                // navigate to the next url and the callback is this function (recursion)
                page.open(urls[i], genericCallback());
            } else {
                // try navigate to the next url (it is undefined because it is the last element) so the callback is exit
                page.open(urls[i], function () {
                    phantom.exit();
                });
            }
        }
    };
};

// start from the first url
page.open(urls[i], genericCallback());
var page=require('webpage').create();
//要导航到的URL
变量URL=[
'http://phantomjs.org/',
'https://twitter.com/sidanmor',
'https://github.com/sidanmor'
];
var i=0;
//递归函数
var genericCallback=函数(){
返回功能(状态){
log(“URL:+URL[i]);
控制台日志(“状态:+状态”);
//如果导航出现问题,请退出
如果(!status | | status=='fail')幻影.exit();
i++;
如果(状态==“成功”){
//--你的东西在这里------------------
//在这里做你的东西…我正在给这页拍照
render('example'+i+'.png');
//-----------------------------------------
if(i
使用排队进程,示例:

var page=require('webpage').create();
//队列类帮助器
var Queue=函数(){
这是。_tasks=[];
};
Queue.prototype.add=函数(fn,范围){
this._tasks.push({fn:fn,scope:scope});
归还这个;
};
Queue.prototype.process=函数(){
var-proxy,self=this;
task=这个。_tasks.shift();
如果(!task){return;}
proxy={end:function(){self.process();}};
task.fn.call(task.scope,proxy);
归还这个;
};
Queue.prototype.clear=函数(){
此任务。_tasks=[];返回此任务;
};
//初始化页面。。。。。
var q=新队列();
q、 添加(功能(代理){
page.open(url1,函数(){
//第页,评估
proxy.end();
});            
});
q、 添加(功能(代理){
page.open(url2,函数(){
//第页,评估
proxy.end();
});            
});
q、 添加(功能(代理){
page.open(urln,function(){
//第页,评估
proxy.end();
});            
});
// .....
q、 添加(功能(代理){
幻影。退出()
proxy.end();
});
q、 过程();

我希望这是有用的,尊敬的。

我发现了这一点,但我希望以一种简单的方式实现它,就像我目前使用的方式一样。是的,但从你的问题来看,不太清楚你在做这件事时遇到了什么障碍。你基本上只写“它不起作用”和“认为它应该以某种方式起作用”。这是很好的描述。因此,即使是知道这一点的人也可能无法以知道答案的方式解读你的问题。代码示例添加了良好的上下文,但您也应该指出您希望在代码示例中使用的内容。使用一些调试信息更新了我的问题您是否仔细检查了三个函数中的前两个是否已执行?是否
console.log
证明前两个函数未运行?。我还试着通过注释掉另外两个代码来运行第一个代码,效果很好。这是有道理的。让我试试看,然后再给你回复。很有帮助,很简单!非常感谢。同时调用多个page.open会导致PhantomJS出现问题(或者仅仅是因为经验),这是有原因的吗?我遇到了一个相关的问题,正在寻找解决方法。我来到这个页面是因为我们遇到了类似的问题。奇怪的是,它是在软件运行时同时打开多达70个URL(全部指向
文件://
)之后才开始出现的。所以它绝对有可能打开多个URL,但正如我们的情况所证明的,它可能有任意的问题。我用大量的页面尝试了这个方法,结果在ubuntu上出现了一个分段错误。
// first page
var urlA = "http://first/url"
var pageA = require('webpage').create()

pageA.open(urlA, function(status){
    if (status){
        setTimeout(openPageB, 100) // open second page call
    } else{
        phantom.exit(1)
    }
})

// second page
var urlB = "http://second/url"
var pageB = require('webpage').create()

function openPageB(){
    pageB.open(urlB, function(){
        // ... 
        // ...
    })
}
var page = require('webpage').create();

// the urls to navigate to
var urls = [
    'http://phantomjs.org/',
    'https://twitter.com/sidanmor',
    'https://github.com/sidanmor'
];

var i = 0;

// the recursion function
var genericCallback = function () {
    return function (status) {
        console.log("URL: " + urls[i]);
        console.log("Status: " + status);
        // exit if there was a problem with the navigation
        if (!status || status === 'fail') phantom.exit();

        i++;

        if (status === "success") {

            //-- YOUR STUFF HERE ---------------------- 
            // do your stuff here... I'm taking a picture of the page
            page.render('example' + i + '.png');
            //-----------------------------------------

            if (i < urls.length) {
                // navigate to the next url and the callback is this function (recursion)
                page.open(urls[i], genericCallback());
            } else {
                // try navigate to the next url (it is undefined because it is the last element) so the callback is exit
                page.open(urls[i], function () {
                    phantom.exit();
                });
            }
        }
    };
};

// start from the first url
page.open(urls[i], genericCallback());